diff options
author | Zachary Turner <zturner@google.com> | 2017-01-25 21:17:40 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2017-01-25 21:17:40 +0000 |
commit | 29da5db7a0bb0fefbebc1e8ecaa1da557130cd4d (patch) | |
tree | 26eecd515187d7a13ee811dd2a3eddcac2e0fbe2 /llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp | |
parent | 6ec3b468ddd4448814194091a42e63f026adadeb (diff) | |
download | bcm5719-llvm-29da5db7a0bb0fefbebc1e8ecaa1da557130cd4d.tar.gz bcm5719-llvm-29da5db7a0bb0fefbebc1e8ecaa1da557130cd4d.zip |
[pdb] Correctly parse the hash adjusters table from TPI stream.
This is not a list of pairs, it is a hash table data structure. We now
correctly parse this out and dump it from llvm-pdbdump.
We still need to understand the conditions that lead to a type
getting an entry in the hash adjuster table. That will be done
in a followup investigation / patch.
Differential Revision: https://reviews.llvm.org/D29090
llvm-svn: 293090
Diffstat (limited to 'llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp')
-rw-r--r-- | llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp | 138 |
1 files changed, 80 insertions, 58 deletions
diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp index 62c6fb42f56..78a98724460 100644 --- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -510,17 +510,19 @@ static void printTypeIndexOffset(raw_ostream &OS, OS << "{" << TIOff.Type.getIndex() << ", " << TIOff.Offset << "}"; } -static void dumpTpiHash(ScopedPrinter &P, TpiStream &Tpi) { - if (!opts::raw::DumpTpiHash) - return; - DictScope DD(P, "Hash"); - P.printNumber("Number of Hash Buckets", Tpi.NumHashBuckets()); - P.printNumber("Hash Key Size", Tpi.getHashKeySize()); - P.printList("Values", Tpi.getHashValues()); - P.printList("Type Index Offsets", Tpi.getTypeIndexOffsets(), - printTypeIndexOffset); - P.printList("Hash Adjustments", Tpi.getHashAdjustments(), - printTypeIndexOffset); +namespace { +class RecordBytesVisitor : public TypeVisitorCallbacks { +public: + explicit RecordBytesVisitor(ScopedPrinter &P) : P(P) {} + + Error visitTypeEnd(CVType &Record) override { + P.printBinaryBlock("Bytes", Record.content()); + return Error::success(); + } + +private: + ScopedPrinter &P; +}; } Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { @@ -528,6 +530,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { bool DumpRecordBytes = false; bool DumpRecords = false; + bool DumpTpiHash = false; StringRef Label; StringRef VerLabel; if (StreamIdx == StreamTPI) { @@ -537,6 +540,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { } DumpRecordBytes = opts::raw::DumpTpiRecordBytes; DumpRecords = opts::raw::DumpTpiRecords; + DumpTpiHash = opts::raw::DumpTpiHash; Label = "Type Info Stream (TPI)"; VerLabel = "TPI Version"; } else if (StreamIdx == StreamIPI) { @@ -549,80 +553,98 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { Label = "Type Info Stream (IPI)"; VerLabel = "IPI Version"; } - if (!DumpRecordBytes && !DumpRecords && !opts::raw::DumpModuleSyms) + if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash && + !opts::raw::DumpModuleSyms) return Error::success(); + bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash; + auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream(); if (!Tpi) return Tpi.takeError(); - // Even if the user doesn't want to dump type records, we still need to - // iterate them in order to build the type database. So when they want to - // dump symbols but not types, don't stick a dumper on the end, just build - // the type database. + std::unique_ptr<DictScope> StreamScope; + std::unique_ptr<ListScope> RecordScope; + + if (!IsSilentDatabaseBuild) { + StreamScope = llvm::make_unique<DictScope>(P, Label); + P.printNumber(VerLabel, Tpi->getTpiVersion()); + P.printNumber("Record count", Tpi->NumTypeRecords()); + } + TypeDatabaseVisitor DBV(TypeDB); CompactTypeDumpVisitor CTDV(TypeDB, &P); TypeDumpVisitor TDV(TypeDB, &P, false); + RecordBytesVisitor RBV(P); TypeDeserializer Deserializer; + + // We always need to deserialize and add it to the type database. This is + // true if even if we're not dumping anything, because we could need the + // type database for the purposes of dumping symbols. TypeVisitorCallbackPipeline Pipeline; Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(DBV); - CVTypeVisitor Visitor(Pipeline); - - if (DumpRecords || DumpRecordBytes) { - DictScope D(P, Label); - - P.printNumber(VerLabel, Tpi->getTpiVersion()); - P.printNumber("Record count", Tpi->NumTypeRecords()); - ListScope L(P, "Records"); - - bool HadError = false; + // If we're in dump mode, add a dumper with the appropriate detail level. + if (DumpRecords) { if (opts::raw::CompactRecords) Pipeline.addCallbackToPipeline(CTDV); else Pipeline.addCallbackToPipeline(TDV); + } + if (DumpRecordBytes) + Pipeline.addCallbackToPipeline(RBV); - for (auto Type : Tpi->types(&HadError)) { - std::unique_ptr<DictScope> Scope; - if (!opts::raw::CompactRecords) - Scope.reset(new DictScope(P, "")); + CVTypeVisitor Visitor(Pipeline); - if (DumpRecords) { - if (auto EC = Visitor.visitTypeRecord(Type)) - return EC; - } + if (DumpRecords || DumpRecordBytes) + RecordScope = llvm::make_unique<ListScope>(P, "Records"); - if (DumpRecordBytes) - P.printBinaryBlock("Bytes", Type.content()); - } - dumpTpiHash(P, *Tpi); - if (HadError) - return make_error<RawError>(raw_error_code::corrupt_file, - "TPI stream contained corrupt record"); - { - ListScope L(P, "TypeIndexOffsets"); - for (const auto &IO : Tpi->getTypeIndexOffsets()) { - P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(), - (uint32_t)IO.Offset) - .str()); - } - } + bool HadError = false; + + TypeIndex T(TypeIndex::FirstNonSimpleIndex); + for (auto Type : Tpi->types(&HadError)) { + std::unique_ptr<DictScope> OneRecordScope; - } else if (opts::raw::DumpModuleSyms) { + if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords) + OneRecordScope = llvm::make_unique<DictScope>(P, ""); - bool HadError = false; - for (auto Type : Tpi->types(&HadError)) { - if (auto EC = Visitor.visitTypeRecord(Type)) - return EC; + if (auto EC = Visitor.visitTypeRecord(Type)) + return EC; + } + if (HadError) + return make_error<RawError>(raw_error_code::corrupt_file, + "TPI stream contained corrupt record"); + + if (DumpTpiHash) { + DictScope DD(P, "Hash"); + P.printNumber("Number of Hash Buckets", Tpi->NumHashBuckets()); + P.printNumber("Hash Key Size", Tpi->getHashKeySize()); + P.printList("Values", Tpi->getHashValues()); + + ListScope LHA(P, "Adjusters"); + auto ExpectedST = File.getStringTable(); + if (!ExpectedST) + return ExpectedST.takeError(); + const auto &ST = *ExpectedST; + for (const auto &E : Tpi->getHashAdjusters()) { + DictScope DHA(P); + StringRef Name = ST.getStringForID(E.first); + P.printString("Type", Name); + P.printHex("TI", E.second); } + } - dumpTpiHash(P, *Tpi); - if (HadError) - return make_error<RawError>(raw_error_code::corrupt_file, - "TPI stream contained corrupt record"); + if (!IsSilentDatabaseBuild) { + ListScope L(P, "TypeIndexOffsets"); + for (const auto &IO : Tpi->getTypeIndexOffsets()) { + P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(), + (uint32_t)IO.Offset) + .str()); + } } + P.flush(); return Error::success(); } |