[llvm-pdbutil] Dump raw bytes of type and id records.

llvm-svn: 306167
This commit is contained in:
Zachary Turner 2017-06-23 21:50:54 +00:00
parent 2c19c1be56
commit c2f5b4bfd9
10 changed files with 146 additions and 1 deletions

View File

@ -61,6 +61,8 @@ public:
void reset(ArrayRef<uint8_t> Data, uint32_t RecordCountHint);
void reset(StringRef Data, uint32_t RecordCountHint);
uint32_t getOffsetOfType(TypeIndex Index);
CVType getType(TypeIndex Index) override;
StringRef getTypeName(TypeIndex Index) override;
bool contains(TypeIndex Index) override;

View File

@ -16,6 +16,7 @@
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Error.h"
@ -57,6 +58,8 @@ public:
codeview::LazyRandomTypeCollection &typeCollection() { return *Types; }
BinarySubstreamRef getTypeRecordsSubstream() const;
Error commit();
private:
@ -65,6 +68,8 @@ private:
std::unique_ptr<codeview::LazyRandomTypeCollection> Types;
BinarySubstreamRef TypeRecordsSubstream;
codeview::CVTypeArray TypeRecords;
std::unique_ptr<BinaryStream> HashStream;

View File

@ -170,6 +170,10 @@ struct BinarySubstreamRef {
uint32_t Offset; // Offset in the parent stream
BinaryStreamRef StreamData; // Stream Data
BinarySubstreamRef slice(uint32_t Off, uint32_t Size) const {
BinaryStreamRef SubSub = StreamData.slice(Off, Size);
return {Off + Offset, SubSub};
}
uint32_t size() const { return StreamData.getLength(); }
bool empty() const { return size() == 0; }
};

View File

@ -67,6 +67,13 @@ void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data,
reset(toStringRef(Data), RecordCountHint);
}
uint32_t LazyRandomTypeCollection::getOffsetOfType(TypeIndex Index) {
error(ensureTypeExists(Index));
assert(contains(Index));
return Records[Index.toArrayIndex()].Offset;
}
CVType LazyRandomTypeCollection::getType(TypeIndex Index) {
error(ensureTypeExists(Index));
assert(contains(Index));

View File

@ -66,7 +66,13 @@ Error TpiStream::reload() {
"TPI Stream Invalid number of hash buckets.");
// The actual type records themselves come from this stream
if (auto EC = Reader.readArray(TypeRecords, Header->TypeRecordBytes))
if (auto EC =
Reader.readSubstream(TypeRecordsSubstream, Header->TypeRecordBytes))
return EC;
BinaryStreamReader RecordReader(TypeRecordsSubstream.StreamData);
if (auto EC =
RecordReader.readArray(TypeRecords, TypeRecordsSubstream.size()))
return EC;
// Hash indices, hash values, etc come from the hash stream.
@ -135,6 +141,10 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; }
uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const {
return TypeRecordsSubstream;
}
FixedStreamArray<support::ulittle32_t> TpiStream::getHashValues() const {
return HashValues;
}

View File

@ -0,0 +1,27 @@
; RUN: llvm-pdbutil bytes -type=0x1002 %p/Inputs/empty.pdb | FileCheck --check-prefix=TYPE %s
; RUN: llvm-pdbutil bytes -id=0x1007 %p/Inputs/empty.pdb | FileCheck --check-prefix=ID %s
; RUN: llvm-pdbutil bytes -type=0x2000 %p/Inputs/empty.pdb | FileCheck --check-prefix=INVALID-TYPE %s
; RUN: llvm-pdbutil bytes -id=0x2000 %p/Inputs/empty.pdb | FileCheck --check-prefix=INVALID-ID %s
TYPE: Type (TPI) Records
TYPE-NEXT: ============================================================
TYPE-NEXT: Type 0x1002 (
TYPE-NEXT: 12050: 4A000312 02150300 01006170 6172746D 656E7400 02150300 02007369 6E676C65 |J.........apartment.......single|
TYPE-NEXT: 12070: 00F3F2F1 02150300 03006672 656500F1 02150300 04006E65 75747261 6C00F2F1 |..........free........neutral...|
TYPE-NEXT: 12090: 02150300 0500626F 746800F1 |......both..|
TYPE-NEXT: )
ID: Index (IPI) Records
ID-NEXT: ============================================================
ID-NEXT: Type 0x1007 (
ID-NEXT: 140C4: 2E000516 00000000 643A5C73 72635C6C 6C766D5C 74657374 5C446562 7567496E |........d:\src\llvm\test\DebugIn|
ID-NEXT: 140E4: 666F5C50 44425C49 6E707574 7300F2F1 |fo\PDB\Inputs...|
ID-NEXT: )
INVALID-TYPE: Type (TPI) Records
INVALID-TYPE-NEXT: ============================================================
INVALID-TYPE-NEXT: Error: TypeIndex 0x2000 does not exist
INVALID-ID: Index (IPI) Records
INVALID-ID-NEXT: ============================================================
INVALID-ID-NEXT: Error: TypeIndex 0x2000 does not exist

View File

@ -12,16 +12,20 @@
#include "StreamUtil.h"
#include "llvm-pdbutil.h"
#include "llvm/DebugInfo/CodeView/Formatters.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatVariadic.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::msf;
using namespace llvm::pdb;
@ -154,6 +158,16 @@ Error BytesOutputStyle::dump() {
P.NewLine();
}
if (!opts::bytes::TypeIndex.empty()) {
dumpTypeIndex(StreamTPI, opts::bytes::TypeIndex);
P.NewLine();
}
if (!opts::bytes::IdIndex.empty()) {
dumpTypeIndex(StreamIPI, opts::bytes::IdIndex);
P.NewLine();
}
return Error::success();
}
@ -253,6 +267,36 @@ void BytesOutputStyle::dumpECData() {
P.formatMsfStreamData("Edit and Continue Data", File, Layout, NS);
}
void BytesOutputStyle::dumpTypeIndex(uint32_t StreamIdx,
ArrayRef<uint32_t> Indices) {
assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
assert(!Indices.empty());
bool IsTpi = (StreamIdx == StreamTPI);
StringRef Label = IsTpi ? "Type (TPI) Records" : "Index (IPI) Records";
printHeader(P, Label);
auto &Stream = Err(IsTpi ? File.getPDBTpiStream() : File.getPDBIpiStream());
AutoIndent Indent(P);
auto Substream = Stream.getTypeRecordsSubstream();
auto &Types = Err(initializeTypes(StreamIdx));
auto Layout = File.getStreamLayout(StreamIdx);
for (const auto &Id : Indices) {
TypeIndex TI(Id);
if (TI.toArrayIndex() >= Types.capacity()) {
P.formatLine("Error: TypeIndex {0} does not exist", TI);
continue;
}
auto Type = Types.getType(TI);
uint32_t Offset = Types.getOffsetOfType(TI);
auto OneType = Substream.slice(Offset, Type.length());
P.formatMsfStreamData(formatv("Type {0}", TI).str(), File, Layout, OneType);
}
}
void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) {
printHeader(P, "MSF Bytes");
@ -268,6 +312,26 @@ void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) {
P.formatBinary("Bytes", Data, Min);
}
Expected<codeview::LazyRandomTypeCollection &>
BytesOutputStyle::initializeTypes(uint32_t StreamIdx) {
auto &TypeCollection = (StreamIdx == StreamTPI) ? TpiTypes : IpiTypes;
if (TypeCollection)
return *TypeCollection;
auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
: File.getPDBIpiStream();
if (!Tpi)
return Tpi.takeError();
auto &Types = Tpi->typeArray();
uint32_t Count = Tpi->getNumTypeRecords();
auto Offsets = Tpi->getTypeIndexOffsets();
TypeCollection =
llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
return *TypeCollection;
}
void BytesOutputStyle::dumpStreamBytes() {
if (StreamPurposes.empty())
discoverStreamPurposes(File, StreamPurposes);

View File

@ -17,6 +17,10 @@
namespace llvm {
namespace codeview {
class LazyRandomTypeCollection;
}
namespace pdb {
class PDBFile;
@ -40,6 +44,14 @@ private:
void dumpTypeServerMap();
void dumpECData();
void dumpTypeIndex(uint32_t StreamIdx, ArrayRef<uint32_t> Indices);
Expected<codeview::LazyRandomTypeCollection &>
initializeTypes(uint32_t StreamIdx);
std::unique_ptr<codeview::LazyRandomTypeCollection> TpiTypes;
std::unique_ptr<codeview::LazyRandomTypeCollection> IpiTypes;
PDBFile &File;
LinePrinter P;
ExitOnError Err;

View File

@ -270,6 +270,7 @@ namespace bytes {
cl::OptionCategory MsfBytes("MSF File Options");
cl::OptionCategory DbiBytes("Dbi Stream Options");
cl::OptionCategory PdbBytes("PDB Stream Options");
cl::OptionCategory Types("Type Options");
llvm::Optional<NumberRange> DumpBlockRange;
llvm::Optional<NumberRange> DumpByteRange;
@ -306,6 +307,16 @@ cl::opt<bool> TypeServerMap("type-server", cl::desc("Dump type server map"),
cl::opt<bool> ECData("ec", cl::desc("Dump edit and continue map"),
cl::sub(BytesSubcommand), cl::cat(DbiBytes));
cl::list<uint32_t>
TypeIndex("type",
cl::desc("Dump the type record with the given type index"),
cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand),
cl::cat(TypeCategory));
cl::list<uint32_t>
IdIndex("id", cl::desc("Dump the id record with the given type index"),
cl::ZeroOrMore, cl::CommaSeparated, cl::sub(BytesSubcommand),
cl::cat(TypeCategory));
cl::list<std::string> InputFilenames(cl::Positional,
cl::desc("<input PDB files>"),
cl::OneOrMore, cl::sub(BytesSubcommand));

View File

@ -110,6 +110,9 @@ extern llvm::cl::opt<bool> FileInfo;
extern llvm::cl::opt<bool> TypeServerMap;
extern llvm::cl::opt<bool> ECData;
extern llvm::cl::list<uint32_t> TypeIndex;
extern llvm::cl::list<uint32_t> IdIndex;
} // namespace bytes
namespace dump {