forked from OSchip/llvm-project
[llvm-pdbutil] Dump raw bytes of type and id records.
llvm-svn: 306167
This commit is contained in:
parent
2c19c1be56
commit
c2f5b4bfd9
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue