forked from OSchip/llvm-project
pdbdump: print out TPI hashes.
Differential Revision: http://reviews.llvm.org/D20945 llvm-svn: 271736
This commit is contained in:
parent
bc929e4765
commit
fd97bf1f76
|
@ -221,7 +221,7 @@ public:
|
|||
return FixedStreamArrayIterator<T>(*this, 0);
|
||||
}
|
||||
FixedStreamArrayIterator<T> end() const {
|
||||
return FixedStreamArrayIterator<T>(*this);
|
||||
return FixedStreamArrayIterator<T>(*this, size());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -230,13 +230,8 @@ private:
|
|||
|
||||
template <typename T> class FixedStreamArrayIterator {
|
||||
public:
|
||||
FixedStreamArrayIterator(const FixedStreamArray<T> &Array)
|
||||
: Array(Array), Index(uint32_t(-1)) {}
|
||||
FixedStreamArrayIterator(const FixedStreamArray<T> &Array, uint32_t ArrayIndex)
|
||||
: Array(Array), Index(ArrayIndex) {
|
||||
if (Array.size() <= Index)
|
||||
Index = uint32_t(-1);
|
||||
}
|
||||
FixedStreamArrayIterator(const FixedStreamArray<T> &Array, uint32_t Index)
|
||||
: Array(Array), Index(Index) {}
|
||||
|
||||
bool operator==(const FixedStreamArrayIterator<T> &R) {
|
||||
assert(&Array == &R.Array);
|
||||
|
@ -250,10 +245,8 @@ public:
|
|||
const T &operator*() const { return Array[Index]; }
|
||||
|
||||
FixedStreamArrayIterator<T> &operator++() {
|
||||
if (Index == uint32_t(-1))
|
||||
return *this;
|
||||
if (++Index >= Array.size())
|
||||
Index = uint32_t(-1);
|
||||
assert(Index < Array.size());
|
||||
++Index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H
|
||||
#define LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
namespace llvm {
|
||||
|
@ -72,6 +73,13 @@ struct SecMapEntry {
|
|||
support::ulittle32_t SecByteLength; // Byte count of the segment or group.
|
||||
};
|
||||
|
||||
// Used for serialized hash table in TPI stream.
|
||||
// In the reference, it is an array of TI and cbOff pair.
|
||||
struct TypeIndexOffset {
|
||||
codeview::TypeIndex Type;
|
||||
support::ulittle32_t Offset;
|
||||
};
|
||||
|
||||
} // namespace pdb
|
||||
} // namespace llvm
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "llvm/DebugInfo/PDB/PDBTypes.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
|
@ -41,6 +43,10 @@ public:
|
|||
uint16_t getTypeHashStreamIndex() const;
|
||||
uint16_t getTypeHashStreamAuxIndex() const;
|
||||
|
||||
codeview::FixedStreamArray<support::ulittle32_t> getHashValues() const;
|
||||
codeview::FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
|
||||
codeview::FixedStreamArray<TypeIndexOffset> getHashAdjustments() const;
|
||||
|
||||
iterator_range<codeview::CVTypeArray::Iterator> types(bool *HadError) const;
|
||||
|
||||
private:
|
||||
|
@ -49,9 +55,11 @@ private:
|
|||
HashFunctionType HashFunction;
|
||||
|
||||
codeview::CVTypeArray TypeRecords;
|
||||
codeview::StreamRef TypeIndexOffsetBuffer;
|
||||
codeview::StreamRef HashValuesBuffer;
|
||||
codeview::StreamRef HashAdjBuffer;
|
||||
|
||||
std::unique_ptr<MappedBlockStream> HashStream;
|
||||
codeview::FixedStreamArray<support::ulittle32_t> HashValues;
|
||||
codeview::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets;
|
||||
codeview::FixedStreamArray<TypeIndexOffset> HashAdjustments;
|
||||
|
||||
const HeaderInfo *Header;
|
||||
};
|
||||
|
|
|
@ -11,11 +11,13 @@
|
|||
|
||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||
#include "llvm/DebugInfo/CodeView/StreamReader.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
|
||||
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
|
@ -99,20 +101,23 @@ Error TpiStream::reload() {
|
|||
return EC;
|
||||
|
||||
// Hash indices, hash values, etc come from the hash stream.
|
||||
MappedBlockStream HS(Header->HashStreamIndex, Pdb);
|
||||
codeview::StreamReader HSR(HS);
|
||||
HashStream.reset(new MappedBlockStream(Header->HashStreamIndex, Pdb));
|
||||
codeview::StreamReader HSR(*HashStream);
|
||||
uint32_t NumHashValues = Header->HashValueBuffer.Length / sizeof(ulittle32_t);
|
||||
HSR.setOffset(Header->HashValueBuffer.Off);
|
||||
if (auto EC =
|
||||
HSR.readStreamRef(HashValuesBuffer, Header->HashValueBuffer.Length))
|
||||
return EC;
|
||||
|
||||
HSR.setOffset(Header->HashAdjBuffer.Off);
|
||||
if (auto EC = HSR.readStreamRef(HashAdjBuffer, Header->HashAdjBuffer.Length))
|
||||
if (auto EC = HSR.readArray(HashValues, NumHashValues))
|
||||
return EC;
|
||||
|
||||
HSR.setOffset(Header->IndexOffsetBuffer.Off);
|
||||
if (auto EC = HSR.readStreamRef(TypeIndexOffsetBuffer,
|
||||
Header->IndexOffsetBuffer.Length))
|
||||
uint32_t NumTypeIndexOffsets =
|
||||
Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
|
||||
if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
|
||||
return EC;
|
||||
|
||||
HSR.setOffset(Header->HashAdjBuffer.Off);
|
||||
uint32_t NumHashAdjustments =
|
||||
Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset);
|
||||
if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments))
|
||||
return EC;
|
||||
|
||||
return Error::success();
|
||||
|
@ -139,6 +144,21 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
|
|||
return Header->HashAuxStreamIndex;
|
||||
}
|
||||
|
||||
codeview::FixedStreamArray<support::ulittle32_t>
|
||||
TpiStream::getHashValues() const {
|
||||
return HashValues;
|
||||
}
|
||||
|
||||
codeview::FixedStreamArray<TypeIndexOffset>
|
||||
TpiStream::getTypeIndexOffsets() const {
|
||||
return TypeIndexOffsets;
|
||||
}
|
||||
|
||||
codeview::FixedStreamArray<TypeIndexOffset>
|
||||
TpiStream::getHashAdjustments() const {
|
||||
return HashAdjustments;
|
||||
}
|
||||
|
||||
iterator_range<codeview::CVTypeArray::Iterator>
|
||||
TpiStream::types(bool *HadError) const {
|
||||
return llvm::make_range(TypeRecords.begin(HadError), TypeRecords.end());
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
; RUN: -raw-sym-record-bytes -raw-publics -raw-module-files -raw-stream-name=/names \
|
||||
; RUN: -raw-stream-summary -raw-stream-blocks -raw-ipi-records -raw-ipi-record-bytes \
|
||||
; RUN: -raw-section-contribs -raw-section-map -raw-section-headers -raw-line-info \
|
||||
; RUN: %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
|
||||
; RUN: -raw-tpi-hash %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
|
||||
; RUN: llvm-pdbdump -raw-all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
|
||||
; RUN: llvm-pdbdump -raw-headers -raw-stream-name=/names -raw-modules -raw-module-files \
|
||||
; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
|
||||
|
@ -141,6 +141,11 @@
|
|||
; EMPTY-NEXT: 0040: 0500626F 746800F1 |..both..|
|
||||
; EMPTY-NEXT: )
|
||||
; EMPTY-NEXT: }
|
||||
; EMPTY: Hash {
|
||||
; EMPTY-NEXT: Values: [205956, 163561, 59811, 208239, 16377, 247078, 194342, 254156, 194536, 167492, 185421, 119540, 261871, 198119, 48056, 251486, 134580, 148190, 113636, 53336, 55779, 220695, 198114, 148734, 81128, 60158, 217249, 174209, 159978, 249504, 141941, 238785, 6214, 94935, 151449, 135589, 73373, 96512, 254299, 17744, 239514, 173189, 130544, 204437, 238560, 144673, 115151, 197306, 256035, 101096, 231280, 52156, 48854, 170035, 177041, 102745, 16947, 183703, 98548, 35693, 171328, 203640, 139292, 49018, 43821, 202555, 165040, 215835, 142625, 52534, 44186, 103930, 110942, 17991, 213215]
|
||||
; EMPTY-NEXT: Type Index Offsets: [{4096, 0}]
|
||||
; EMPTY-NEXT: Hash Adjustments: []
|
||||
; EMPTY-NEXT: }
|
||||
; EMPTY: Type Info Stream (IPI) {
|
||||
; EMPTY-NEXT: IPI Version: 20040203
|
||||
; EMPTY-NEXT: Record count: 15
|
||||
|
@ -217,6 +222,11 @@
|
|||
; EMPTY-NEXT: 0000: 42100000 01000000 6C000000 0100F2F1 |B.......l.......|
|
||||
; EMPTY-NEXT: )
|
||||
; EMPTY-NEXT: }
|
||||
; EMPTY: Hash {
|
||||
; EMPTY-NEXT: Values: [7186, 7198, 7180, 7191, 7201, 7241, 7249, 80727, 154177, 75189, 253662, 193467, 222705, 186099, 257108]
|
||||
; EMPTY-NEXT: Type Index Offsets: [{4096, 0}]
|
||||
; EMPTY-NEXT: Hash Adjustments: []
|
||||
; EMPTY-NEXT: }
|
||||
; EMPTY: DBI Stream {
|
||||
; EMPTY-NEXT: Dbi Version: 19990903
|
||||
; EMPTY-NEXT: Age: 1
|
||||
|
|
|
@ -264,6 +264,23 @@ Error LLVMOutputStyle::dumpNamedStream() {
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
static void printTypeIndexOffset(raw_ostream &OS,
|
||||
const TypeIndexOffset &TIOff) {
|
||||
OS << "{" << TIOff.Type.getIndex() << ", " << TIOff.Offset << "}";
|
||||
}
|
||||
|
||||
static void dumpTpiHash(ScopedPrinter &P, TpiStream &Tpi) {
|
||||
if (!opts::DumpTpiHash)
|
||||
return;
|
||||
DictScope DD(P, "Hash");
|
||||
codeview::FixedStreamArray<support::ulittle32_t> S = Tpi.getHashValues();
|
||||
P.printList("Values", Tpi.getHashValues());
|
||||
P.printList("Type Index Offsets", Tpi.getTypeIndexOffsets(),
|
||||
printTypeIndexOffset);
|
||||
P.printList("Hash Adjustments", Tpi.getHashAdjustments(),
|
||||
printTypeIndexOffset);
|
||||
}
|
||||
|
||||
Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
|
||||
assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
|
||||
|
||||
|
@ -309,6 +326,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
|
|||
if (DumpRecordBytes)
|
||||
P.printBinaryBlock("Bytes", Type.Data);
|
||||
}
|
||||
dumpTpiHash(P, Tpi);
|
||||
if (HadError)
|
||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||
"TPI stream contained corrupt record");
|
||||
|
@ -325,6 +343,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
|
|||
TD.dump(Type);
|
||||
|
||||
TD.setPrinter(OldP);
|
||||
dumpTpiHash(P, Tpi);
|
||||
if (HadError)
|
||||
return make_error<RawError>(raw_error_code::corrupt_file,
|
||||
"TPI stream contained corrupt record");
|
||||
|
|
|
@ -113,6 +113,9 @@ cl::opt<bool> DumpTpiRecordBytes(
|
|||
"raw-tpi-record-bytes",
|
||||
cl::desc("dump CodeView type record raw bytes from TPI stream"),
|
||||
cl::cat(NativeOptions));
|
||||
cl::opt<bool> DumpTpiHash("raw-tpi-hash",
|
||||
cl::desc("dump CodeView TPI hash stream"),
|
||||
cl::cat(NativeOptions));
|
||||
cl::opt<bool>
|
||||
DumpIpiRecords("raw-ipi-records",
|
||||
cl::desc("dump CodeView type records from IPI stream"),
|
||||
|
@ -276,6 +279,8 @@ bool isRawDumpEnabled() {
|
|||
return true;
|
||||
if (opts::DumpTpiRecords)
|
||||
return true;
|
||||
if (opts::DumpTpiHash)
|
||||
return true;
|
||||
if (opts::DumpIpiRecords)
|
||||
return true;
|
||||
if (opts::DumpIpiRecordBytes)
|
||||
|
@ -450,6 +455,7 @@ int main(int argc_, const char *argv_[]) {
|
|||
opts::DumpStreamSummary = true;
|
||||
opts::DumpStreamBlocks = true;
|
||||
opts::DumpTpiRecords = true;
|
||||
opts::DumpTpiHash = true;
|
||||
opts::DumpIpiRecords = true;
|
||||
opts::DumpSectionMap = true;
|
||||
opts::DumpSectionContribs = true;
|
||||
|
|
|
@ -27,8 +27,9 @@ extern llvm::cl::opt<OutputStyleTy> RawOutputStyle;
|
|||
extern llvm::cl::opt<bool> DumpHeaders;
|
||||
extern llvm::cl::opt<bool> DumpStreamBlocks;
|
||||
extern llvm::cl::opt<bool> DumpStreamSummary;
|
||||
extern llvm::cl::opt<bool> DumpTpiRecords;
|
||||
extern llvm::cl::opt<bool> DumpTpiHash;
|
||||
extern llvm::cl::opt<bool> DumpTpiRecordBytes;
|
||||
extern llvm::cl::opt<bool> DumpTpiRecords;
|
||||
extern llvm::cl::opt<bool> DumpIpiRecords;
|
||||
extern llvm::cl::opt<bool> DumpIpiRecordBytes;
|
||||
extern llvm::cl::opt<std::string> DumpStreamDataIdx;
|
||||
|
|
Loading…
Reference in New Issue