mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[pdb] handle missing pdb streams more gracefully
Summary: The code we use to read PDBs assumed that streams we ask it to read exist, and would read memory outside a vector and crash if this wasn't the case. This would, for example, cause llvm-pdbdump to crash on PDBs generated by lld. This patch handles such cases more gracefully: the PDB reading code in LLVM now reports errors when asked to get a stream that is not present, and llvm-pdbdump will report missing streams and continue processing streams that are present. Reviewers: ruiu, zturner Subscribers: thakis, amccarth Differential Revision: https://reviews.llvm.org/D27325 llvm-svn: 288722
This commit is contained in:
parent
2bd902d401
commit
73e631de3c
@ -26,7 +26,6 @@ namespace llvm {
|
||||
|
||||
namespace msf {
|
||||
class MappedBlockStream;
|
||||
class WritableStream;
|
||||
}
|
||||
|
||||
namespace pdb {
|
||||
@ -96,7 +95,20 @@ public:
|
||||
|
||||
BumpPtrAllocator &getAllocator() { return Allocator; }
|
||||
|
||||
private:
|
||||
bool hasPDBDbiStream() const;
|
||||
bool hasPDBGlobalsStream();
|
||||
bool hasPDBInfoStream();
|
||||
bool hasPDBIpiStream() const;
|
||||
bool hasPDBPublicsStream();
|
||||
bool hasPDBSymbolStream();
|
||||
bool hasPDBTpiStream() const;
|
||||
bool hasStringTable();
|
||||
|
||||
private:
|
||||
Expected<std::unique_ptr<msf::MappedBlockStream>> safelyCreateIndexedStream(
|
||||
const msf::MSFLayout &Layout, const msf::ReadableStream &MsfData,
|
||||
uint32_t StreamIndex) const;
|
||||
|
||||
BumpPtrAllocator &Allocator;
|
||||
|
||||
std::unique_ptr<msf::ReadableStream> Buffer;
|
||||
|
@ -63,6 +63,7 @@ std::unique_ptr<MappedBlockStream>
|
||||
MappedBlockStream::createIndexedStream(const MSFLayout &Layout,
|
||||
const ReadableStream &MsfData,
|
||||
uint32_t StreamIndex) {
|
||||
assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
|
||||
MSFStreamLayout SL;
|
||||
SL.Blocks = Layout.StreamMap[StreamIndex];
|
||||
SL.Length = Layout.StreamSizes[StreamIndex];
|
||||
@ -334,6 +335,7 @@ std::unique_ptr<WritableMappedBlockStream>
|
||||
WritableMappedBlockStream::createIndexedStream(const MSFLayout &Layout,
|
||||
const WritableStream &MsfData,
|
||||
uint32_t StreamIndex) {
|
||||
assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
|
||||
MSFStreamLayout SL;
|
||||
SL.Blocks = Layout.StreamMap[StreamIndex];
|
||||
SL.Length = Layout.StreamSizes[StreamIndex];
|
||||
|
@ -227,9 +227,10 @@ Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() {
|
||||
if (!DbiS)
|
||||
return DbiS.takeError();
|
||||
|
||||
auto GlobalS = MappedBlockStream::createIndexedStream(
|
||||
auto GlobalS = safelyCreateIndexedStream(
|
||||
ContainerLayout, *Buffer, DbiS->getGlobalSymbolStreamIndex());
|
||||
auto TempGlobals = llvm::make_unique<GlobalsStream>(std::move(GlobalS));
|
||||
if (!GlobalS) return GlobalS.takeError();
|
||||
auto TempGlobals = llvm::make_unique<GlobalsStream>(std::move(*GlobalS));
|
||||
if (auto EC = TempGlobals->reload())
|
||||
return std::move(EC);
|
||||
Globals = std::move(TempGlobals);
|
||||
@ -239,9 +240,9 @@ Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() {
|
||||
|
||||
Expected<InfoStream &> PDBFile::getPDBInfoStream() {
|
||||
if (!Info) {
|
||||
auto InfoS = MappedBlockStream::createIndexedStream(ContainerLayout,
|
||||
*Buffer, StreamPDB);
|
||||
auto TempInfo = llvm::make_unique<InfoStream>(std::move(InfoS));
|
||||
auto InfoS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamPDB);
|
||||
if (!InfoS) return InfoS.takeError();
|
||||
auto TempInfo = llvm::make_unique<InfoStream>(std::move(*InfoS));
|
||||
if (auto EC = TempInfo->reload())
|
||||
return std::move(EC);
|
||||
Info = std::move(TempInfo);
|
||||
@ -251,9 +252,9 @@ Expected<InfoStream &> PDBFile::getPDBInfoStream() {
|
||||
|
||||
Expected<DbiStream &> PDBFile::getPDBDbiStream() {
|
||||
if (!Dbi) {
|
||||
auto DbiS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer,
|
||||
StreamDBI);
|
||||
auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(DbiS));
|
||||
auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamDBI);
|
||||
if (!DbiS) return DbiS.takeError();
|
||||
auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(*DbiS));
|
||||
if (auto EC = TempDbi->reload())
|
||||
return std::move(EC);
|
||||
Dbi = std::move(TempDbi);
|
||||
@ -263,9 +264,9 @@ Expected<DbiStream &> PDBFile::getPDBDbiStream() {
|
||||
|
||||
Expected<TpiStream &> PDBFile::getPDBTpiStream() {
|
||||
if (!Tpi) {
|
||||
auto TpiS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer,
|
||||
StreamTPI);
|
||||
auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(TpiS));
|
||||
auto TpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamTPI);
|
||||
if (!TpiS) return TpiS.takeError();
|
||||
auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(*TpiS));
|
||||
if (auto EC = TempTpi->reload())
|
||||
return std::move(EC);
|
||||
Tpi = std::move(TempTpi);
|
||||
@ -275,9 +276,9 @@ Expected<TpiStream &> PDBFile::getPDBTpiStream() {
|
||||
|
||||
Expected<TpiStream &> PDBFile::getPDBIpiStream() {
|
||||
if (!Ipi) {
|
||||
auto IpiS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer,
|
||||
StreamIPI);
|
||||
auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(IpiS));
|
||||
auto IpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamIPI);
|
||||
if (!IpiS) return IpiS.takeError();
|
||||
auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(*IpiS));
|
||||
if (auto EC = TempIpi->reload())
|
||||
return std::move(EC);
|
||||
Ipi = std::move(TempIpi);
|
||||
@ -291,12 +292,11 @@ Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
|
||||
if (!DbiS)
|
||||
return DbiS.takeError();
|
||||
|
||||
uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex();
|
||||
|
||||
auto PublicS = MappedBlockStream::createIndexedStream(
|
||||
ContainerLayout, *Buffer, PublicsStreamNum);
|
||||
auto PublicS = safelyCreateIndexedStream(
|
||||
ContainerLayout, *Buffer, DbiS->getPublicSymbolStreamIndex());
|
||||
if (!PublicS) return PublicS.takeError();
|
||||
auto TempPublics =
|
||||
llvm::make_unique<PublicsStream>(*this, std::move(PublicS));
|
||||
llvm::make_unique<PublicsStream>(*this, std::move(*PublicS));
|
||||
if (auto EC = TempPublics->reload())
|
||||
return std::move(EC);
|
||||
Publics = std::move(TempPublics);
|
||||
@ -311,10 +311,11 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
|
||||
return DbiS.takeError();
|
||||
|
||||
uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex();
|
||||
auto SymbolS = MappedBlockStream::createIndexedStream(
|
||||
ContainerLayout, *Buffer, SymbolStreamNum);
|
||||
auto SymbolS =
|
||||
safelyCreateIndexedStream(ContainerLayout, *Buffer, SymbolStreamNum);
|
||||
if (!SymbolS) return SymbolS.takeError();
|
||||
|
||||
auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(SymbolS));
|
||||
auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(*SymbolS));
|
||||
if (auto EC = TempSymbols->reload())
|
||||
return std::move(EC);
|
||||
Symbols = std::move(TempSymbols);
|
||||
@ -330,19 +331,61 @@ Expected<NameHashTable &> PDBFile::getStringTable() {
|
||||
|
||||
uint32_t NameStreamIndex = IS->getNamedStreamIndex("/names");
|
||||
|
||||
if (NameStreamIndex == 0)
|
||||
return make_error<RawError>(raw_error_code::no_stream);
|
||||
if (NameStreamIndex >= getNumStreams())
|
||||
return make_error<RawError>(raw_error_code::no_stream);
|
||||
auto NS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer,
|
||||
NameStreamIndex);
|
||||
auto NS =
|
||||
safelyCreateIndexedStream(ContainerLayout, *Buffer, NameStreamIndex);
|
||||
if (!NS) return NS.takeError();
|
||||
|
||||
StreamReader Reader(*NS);
|
||||
StreamReader Reader(**NS);
|
||||
auto N = llvm::make_unique<NameHashTable>();
|
||||
if (auto EC = N->load(Reader))
|
||||
return std::move(EC);
|
||||
StringTable = std::move(N);
|
||||
StringTableStream = std::move(NS);
|
||||
StringTableStream = std::move(*NS);
|
||||
}
|
||||
return *StringTable;
|
||||
}
|
||||
|
||||
bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); }
|
||||
|
||||
bool PDBFile::hasPDBGlobalsStream() {
|
||||
auto DbiS = getPDBDbiStream();
|
||||
if (!DbiS) return false;
|
||||
return DbiS->getGlobalSymbolStreamIndex() < getNumStreams();
|
||||
}
|
||||
|
||||
bool PDBFile::hasPDBInfoStream() { return StreamPDB < getNumStreams(); }
|
||||
|
||||
bool PDBFile::hasPDBIpiStream() const { return StreamIPI < getNumStreams(); }
|
||||
|
||||
bool PDBFile::hasPDBPublicsStream() {
|
||||
auto DbiS = getPDBDbiStream();
|
||||
if (!DbiS) return false;
|
||||
return DbiS->getPublicSymbolStreamIndex() < getNumStreams();
|
||||
}
|
||||
|
||||
bool PDBFile::hasPDBSymbolStream() {
|
||||
auto DbiS = getPDBDbiStream();
|
||||
if (!DbiS) return false;
|
||||
return DbiS->getSymRecordStreamIndex() < getNumStreams();
|
||||
}
|
||||
|
||||
bool PDBFile::hasPDBTpiStream() const { return StreamTPI < getNumStreams(); }
|
||||
|
||||
bool PDBFile::hasStringTable() {
|
||||
auto IS = getPDBInfoStream();
|
||||
if (!IS) return false;
|
||||
return IS->getNamedStreamIndex("/names") < getNumStreams();
|
||||
}
|
||||
|
||||
/// Wrapper around MappedBlockStream::createIndexedStream()
|
||||
/// that checks if a stream with that index actually exists.
|
||||
/// If it does not, the return value will have an MSFError with
|
||||
/// code msf_error_code::no_stream. Else, the return value will
|
||||
/// contain the stream returned by createIndexedStream().
|
||||
Expected<std::unique_ptr<MappedBlockStream>> PDBFile::safelyCreateIndexedStream(
|
||||
const MSFLayout &Layout, const ReadableStream &MsfData,
|
||||
uint32_t StreamIndex) const {
|
||||
if (StreamIndex >= getNumStreams())
|
||||
return make_error<RawError>(raw_error_code::no_stream);
|
||||
return MappedBlockStream::createIndexedStream(Layout, MsfData, StreamIndex);
|
||||
}
|
||||
|
@ -350,11 +350,23 @@ void LLVMOutputStyle::dumpBitVector(StringRef Name, const BitVector &V) {
|
||||
Error LLVMOutputStyle::dumpGlobalsStream() {
|
||||
if (!opts::raw::DumpGlobals)
|
||||
return Error::success();
|
||||
if (!File.hasPDBGlobalsStream()) {
|
||||
P.printString("Globals Stream not present");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
DictScope D(P, "Globals Stream");
|
||||
auto Globals = File.getPDBGlobalsStream();
|
||||
if (!Globals)
|
||||
return Globals.takeError();
|
||||
return handleErrors(Globals.takeError(),
|
||||
[&](const msf::MSFError &E) -> Error {
|
||||
if (E.Code == msf::msf_error_code::no_stream) {
|
||||
P.printString("Globals Stream not present");
|
||||
return Error::success();
|
||||
} else {
|
||||
return make_error<msf::MSFError>(E);
|
||||
}
|
||||
});
|
||||
DictScope D(P, "Globals Stream");
|
||||
|
||||
auto Dbi = File.getPDBDbiStream();
|
||||
if (!Dbi)
|
||||
@ -447,6 +459,10 @@ Error LLVMOutputStyle::dumpStreamBytes() {
|
||||
Error LLVMOutputStyle::dumpInfoStream() {
|
||||
if (!opts::raw::DumpHeaders)
|
||||
return Error::success();
|
||||
if (!File.hasPDBInfoStream()) {
|
||||
P.printString("PDB Stream not present");
|
||||
return Error::success();
|
||||
}
|
||||
auto IS = File.getPDBInfoStream();
|
||||
if (!IS)
|
||||
return IS.takeError();
|
||||
@ -485,11 +501,19 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
|
||||
StringRef Label;
|
||||
StringRef VerLabel;
|
||||
if (StreamIdx == StreamTPI) {
|
||||
if (!File.hasPDBTpiStream()) {
|
||||
P.printString("Type Info Stream (TPI) not present");
|
||||
return Error::success();
|
||||
}
|
||||
DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
|
||||
DumpRecords = opts::raw::DumpTpiRecords;
|
||||
Label = "Type Info Stream (TPI)";
|
||||
VerLabel = "TPI Version";
|
||||
} else if (StreamIdx == StreamIPI) {
|
||||
if (!File.hasPDBIpiStream()) {
|
||||
P.printString("Type Info Stream (IPI) not present");
|
||||
return Error::success();
|
||||
}
|
||||
DumpRecordBytes = opts::raw::DumpIpiRecordBytes;
|
||||
DumpRecords = opts::raw::DumpIpiRecords;
|
||||
Label = "Type Info Stream (IPI)";
|
||||
@ -556,6 +580,10 @@ Error LLVMOutputStyle::dumpDbiStream() {
|
||||
opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo;
|
||||
if (!opts::raw::DumpHeaders && !DumpModules)
|
||||
return Error::success();
|
||||
if (!File.hasPDBDbiStream()) {
|
||||
P.printString("DBI Stream not present");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
auto DS = File.getPDBDbiStream();
|
||||
if (!DS)
|
||||
@ -742,6 +770,10 @@ Error LLVMOutputStyle::dumpDbiStream() {
|
||||
Error LLVMOutputStyle::dumpSectionContribs() {
|
||||
if (!opts::raw::DumpSectionContribs)
|
||||
return Error::success();
|
||||
if (!File.hasPDBDbiStream()) {
|
||||
P.printString("DBI Stream not present");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
auto Dbi = File.getPDBDbiStream();
|
||||
if (!Dbi)
|
||||
@ -789,6 +821,10 @@ Error LLVMOutputStyle::dumpSectionContribs() {
|
||||
Error LLVMOutputStyle::dumpSectionMap() {
|
||||
if (!opts::raw::DumpSectionMap)
|
||||
return Error::success();
|
||||
if (!File.hasPDBDbiStream()) {
|
||||
P.printString("DBI Stream not present");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
auto Dbi = File.getPDBDbiStream();
|
||||
if (!Dbi)
|
||||
@ -813,11 +849,15 @@ Error LLVMOutputStyle::dumpSectionMap() {
|
||||
Error LLVMOutputStyle::dumpPublicsStream() {
|
||||
if (!opts::raw::DumpPublics)
|
||||
return Error::success();
|
||||
if (!File.hasPDBPublicsStream()) {
|
||||
P.printString("Publics Stream not present");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
DictScope D(P, "Publics Stream");
|
||||
auto Publics = File.getPDBPublicsStream();
|
||||
if (!Publics)
|
||||
return Publics.takeError();
|
||||
DictScope D(P, "Publics Stream");
|
||||
|
||||
auto Dbi = File.getPDBDbiStream();
|
||||
if (!Dbi)
|
||||
@ -856,6 +896,10 @@ Error LLVMOutputStyle::dumpPublicsStream() {
|
||||
Error LLVMOutputStyle::dumpSectionHeaders() {
|
||||
if (!opts::raw::DumpSectionHeaders)
|
||||
return Error::success();
|
||||
if (!File.hasPDBDbiStream()) {
|
||||
P.printString("DBI Stream not present");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
auto Dbi = File.getPDBDbiStream();
|
||||
if (!Dbi)
|
||||
@ -885,6 +929,10 @@ Error LLVMOutputStyle::dumpSectionHeaders() {
|
||||
Error LLVMOutputStyle::dumpFpoStream() {
|
||||
if (!opts::raw::DumpFpo)
|
||||
return Error::success();
|
||||
if (!File.hasPDBDbiStream()) {
|
||||
P.printString("DBI Stream not present");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
auto Dbi = File.getPDBDbiStream();
|
||||
if (!Dbi)
|
||||
|
Loading…
Reference in New Issue
Block a user