[pdb] Write the IPI stream.

The IPI stream is structurally identical to the TPI stream, but it
contains different record types.  So we just re-use the TPI writing
code.

llvm-svn: 281638
This commit is contained in:
Zachary Turner 2016-09-15 18:22:31 +00:00
parent d93c4c0137
commit de9ba15511
10 changed files with 72 additions and 8 deletions

View File

@ -42,6 +42,7 @@ public:
InfoStreamBuilder &getInfoBuilder();
DbiStreamBuilder &getDbiBuilder();
TpiStreamBuilder &getTpiBuilder();
TpiStreamBuilder &getIpiBuilder();
Expected<std::unique_ptr<PDBFile>>
build(std::unique_ptr<msf::WritableStream> PdbFileBuffer);
@ -57,6 +58,7 @@ private:
std::unique_ptr<InfoStreamBuilder> Info;
std::unique_ptr<DbiStreamBuilder> Dbi;
std::unique_ptr<TpiStreamBuilder> Tpi;
std::unique_ptr<TpiStreamBuilder> Ipi;
};
}
}

View File

@ -45,7 +45,7 @@ struct TpiStreamHeader;
class TpiStreamBuilder {
public:
explicit TpiStreamBuilder(msf::MSFBuilder &Msf);
explicit TpiStreamBuilder(msf::MSFBuilder &Msf, uint32_t StreamIdx);
~TpiStreamBuilder();
TpiStreamBuilder(const TpiStreamBuilder &) = delete;
@ -77,6 +77,7 @@ private:
std::unique_ptr<msf::ByteStream> HashValueStream;
const TpiStreamHeader *Header;
uint32_t Idx;
};
}
}

View File

@ -62,10 +62,16 @@ DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
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())
@ -79,6 +85,10 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const {
if (auto EC = Tpi->finalizeMsfLayout())
return std::move(EC);
}
if (Ipi) {
if (auto EC = Ipi->finalizeMsfLayout())
return std::move(EC);
}
return Msf->build();
}
@ -113,6 +123,13 @@ PDBFileBuilder::build(std::unique_ptr<msf::WritableStream> PdbFileBuffer) {
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,
@ -166,5 +183,10 @@ Error PDBFileBuilder::commit(const msf::WritableStream &Buffer) {
return EC;
}
if (Ipi) {
if (auto EC = Ipi->commit(Layout, Buffer))
return EC;
}
return Buffer.commit();
}

View File

@ -15,8 +15,9 @@ using namespace llvm::msf;
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() {}
@ -75,7 +76,7 @@ uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
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();
@ -106,8 +107,8 @@ TpiStreamBuilder::build(PDBFile &File, const msf::WritableStream &Buffer) {
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);
@ -126,7 +127,7 @@ Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
return EC;
auto InfoS =
WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamTPI);
WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx);
StreamWriter Writer(*InfoS);
if (auto EC = Writer.writeObject(*Header))

View File

@ -138,6 +138,7 @@ void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
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) {

View File

@ -93,6 +93,7 @@ struct PdbObject {
Optional<PdbInfoStream> PdbStream;
Optional<PdbDbiStream> DbiStream;
Optional<PdbTpiStream> TpiStream;
Optional<PdbTpiStream> IpiStream;
BumpPtrAllocator &Allocator;
};

View File

@ -50,6 +50,9 @@ Error YAMLOutputStyle::dump() {
if (auto EC = dumpTpiStream())
return EC;
if (auto EC = dumpIpiStream())
return EC;
flush();
return Error::success();
}
@ -179,6 +182,26 @@ Error YAMLOutputStyle::dumpTpiStream() {
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();

View File

@ -32,6 +32,7 @@ private:
Error dumpPDBStream();
Error dumpDbiStream();
Error dumpTpiStream();
Error dumpIpiStream();
void flush();

View File

@ -290,6 +290,10 @@ cl::opt<bool> TpiStream("tpi-stream",
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));
@ -371,6 +375,13 @@ static void yamlToPdb(StringRef Path) {
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));
}

View File

@ -73,6 +73,7 @@ extern llvm::cl::opt<bool> DbiStream;
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;
}
}