1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 12:12:47 +01:00

Revert "[CodeView] Provide a common interface for type collections."

This is a squash of ~5 reverts of, well, pretty much everything
I did today.  Something is seriously broken with lit on Windows
right now, and as a result assertions that fire in tests are
triggering failures.  I've been breaking non-Windows bots all
day which has seriously confused me because all my tests have
been passing, and after running lit with -a to view the output
even on successful runs, I find out that the tool is crashing
and yet lit is still reporting it as a success!

At this point I don't even know where to start, so rather than
leave the tree broken for who knows how long, I will get this
back to green, and then once lit is fixed on Windows, hopefully
hopefully fix the remaining set of problems for real.

llvm-svn: 303409
This commit is contained in:
Zachary Turner 2017-05-19 05:57:45 +00:00
parent 92c35d4ced
commit 4a5590fa6b
38 changed files with 570 additions and 845 deletions

View File

@ -32,10 +32,6 @@ public:
uint32_t length() const { return RecordData.size(); }
Kind kind() const { return Type; }
ArrayRef<uint8_t> data() const { return RecordData; }
StringRef str_data() const {
return StringRef(reinterpret_cast<const char *>(RecordData.data()),
RecordData.size());
}
ArrayRef<uint8_t> content() const {
return RecordData.drop_front(sizeof(RecordPrefix));

View File

@ -0,0 +1,61 @@
//===-- CVTypeDumper.h - CodeView type info dumper --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEDUMPER_H
#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEDUMPER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/ScopedPrinter.h"
namespace llvm {
namespace codeview {
class TypeServerHandler;
/// Dumper for CodeView type streams found in COFF object files and PDB files.
class CVTypeDumper {
public:
explicit CVTypeDumper(TypeDatabase &TypeDB,
TypeServerHandler *Handler = nullptr)
: TypeDB(TypeDB), Handler(Handler) {}
/// Dumps one type record. Returns false if there was a type parsing error,
/// and true otherwise. This should be called in order, since the dumper
/// maintains state about previous records which are necessary for cross
/// type references.
Error dump(const CVType &Record, TypeVisitorCallbacks &Dumper);
/// Dumps the type records in Types. Returns false if there was a type stream
/// parse error, and true otherwise.
Error dump(const CVTypeArray &Types, TypeVisitorCallbacks &Dumper);
/// Dumps the type records in Data. Returns false if there was a type stream
/// parse error, and true otherwise. Use this method instead of the
/// CVTypeArray overload when type records are laid out contiguously in
/// memory.
Error dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper);
static void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
TypeIndex TI, TypeDatabase &DB);
private:
TypeDatabase &TypeDB;
TypeServerHandler *Handler;
};
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H

View File

@ -10,15 +10,42 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
class TypeCollection;
class TypeServerHandler;
class TypeVisitorCallbacks;
class CVTypeVisitor {
public:
explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
void addTypeServerHandler(TypeServerHandler &Handler);
Error visitTypeRecord(CVType &Record, TypeIndex Index);
Error visitTypeRecord(CVType &Record);
Error visitMemberRecord(CVMemberRecord Record);
/// Visits the type records in Data. Sets the error flag on parse failures.
Error visitTypeStream(const CVTypeArray &Types);
Error visitTypeStream(CVTypeRange Types);
Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList);
Error visitFieldListMemberStream(BinaryStreamReader Reader);
private:
Expected<bool> handleTypeServer(CVType &Record);
Error finishVisitation(CVType &Record);
/// The interface to the class that gets notified of each visitation.
TypeVisitorCallbacks &Callbacks;
TinyPtrVector<TypeServerHandler *> Handlers;
};
enum VisitorDataSource {
VDS_BytesPresent, // The record bytes are passed into the the visitation
@ -49,8 +76,6 @@ Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS = nullptr);
Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS = nullptr);
Error visitTypeStream(TypeCollection &Types, TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS = nullptr);
} // end namespace codeview
} // end namespace llvm

View File

@ -1,4 +1,4 @@
//===- LazyRandomTypeCollection.h ---------------------------- *- C++ --*-===//
//===- RandomAccessTypeVisitor.h ------------------------------ *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
#ifndef LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
#define LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
@ -21,6 +21,7 @@ namespace llvm {
namespace codeview {
class TypeDatabase;
class TypeServerHandler;
class TypeVisitorCallbacks;
/// \brief Provides amortized O(1) random access to a CodeView type stream.
@ -39,48 +40,32 @@ class TypeVisitorCallbacks;
/// consumer much better access time, because the consumer can find the nearest
/// index in this array, and do a linear scan forward only from there.
///
/// LazyRandomTypeCollection implements this algorithm, but additionally goes
/// one step further by caching offsets of every record that has been visited at
/// RandomAccessTypeVisitor implements this algorithm, but additionally goes one
/// step further by caching offsets of every record that has been visited at
/// least once. This way, even repeated visits of the same record will never
/// require more than one linear scan. For a type stream of N elements divided
/// into M chunks of roughly equal size, this yields a worst case lookup time
/// of O(N/M) and an amortized time of O(1).
class LazyRandomTypeCollection : public TypeCollection {
class RandomAccessTypeVisitor {
typedef FixedStreamArray<TypeIndexOffset> PartialOffsetArray;
public:
explicit LazyRandomTypeCollection(uint32_t RecordCountHint);
LazyRandomTypeCollection(StringRef Data, uint32_t RecordCountHint);
LazyRandomTypeCollection(ArrayRef<uint8_t> Data, uint32_t RecordCountHint);
LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint,
PartialOffsetArray PartialOffsets);
LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint);
RandomAccessTypeVisitor(const CVTypeArray &Types, uint32_t NumRecords,
PartialOffsetArray PartialOffsets);
void reset(ArrayRef<uint8_t> Data);
void reset(StringRef Data);
Error visitTypeIndex(TypeIndex Index, TypeVisitorCallbacks &Callbacks);
CVType getType(TypeIndex Index) override;
StringRef getTypeName(TypeIndex Index) override;
bool contains(TypeIndex Index) override;
uint32_t size() override;
uint32_t capacity() override;
TypeIndex getFirst() override;
Optional<TypeIndex> getNext(TypeIndex Prev) override;
const TypeDatabase &database() const { return Database; }
private:
const TypeDatabase &database() const { return Database; }
Error ensureTypeExists(TypeIndex Index);
Error visitRangeForType(TypeIndex TI);
Error fullScanForType(TypeIndex TI);
Error visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
Error visitOneRecord(TypeIndex TI, uint32_t Offset, CVType &Record);
/// Visited records get automatically added to the type database.
TypeDatabase Database;
/// The type array to allow random access visitation of.
CVTypeArray Types;
const CVTypeArray &Types;
/// The database visitor which adds new records to the database.
TypeDatabaseVisitor DatabaseVisitor;
@ -100,4 +85,4 @@ private:
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
#endif // LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H

View File

@ -20,15 +20,15 @@ namespace llvm {
class ScopedPrinter;
namespace codeview {
class TypeCollection;
class TypeDatabase;
/// Dumper for CodeView symbol streams found in COFF object files and PDB files.
class CVSymbolDumper {
public:
CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types,
CVSymbolDumper(ScopedPrinter &W, TypeDatabase &TypeDB,
std::unique_ptr<SymbolDumpDelegate> ObjDelegate,
bool PrintRecordBytes)
: W(W), Types(Types), ObjDelegate(std::move(ObjDelegate)),
: W(W), TypeDB(TypeDB), ObjDelegate(std::move(ObjDelegate)),
PrintRecordBytes(PrintRecordBytes) {}
/// Dumps one type record. Returns false if there was a type parsing error,
@ -43,7 +43,7 @@ public:
private:
ScopedPrinter &W;
TypeCollection &Types;
TypeDatabase &TypeDB;
std::unique_ptr<SymbolDumpDelegate> ObjDelegate;
bool PrintRecordBytes;

View File

@ -1,38 +0,0 @@
//===- TypeCollection.h - A collection of CodeView type records -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
namespace llvm {
namespace codeview {
class TypeCollection {
public:
virtual ~TypeCollection() = default;
bool empty() { return size() == 0; }
virtual TypeIndex getFirst() = 0;
virtual Optional<TypeIndex> getNext(TypeIndex Prev) = 0;
virtual CVType getType(TypeIndex Index) = 0;
virtual StringRef getTypeName(TypeIndex Index) = 0;
virtual bool contains(TypeIndex Index) = 0;
virtual uint32_t size() = 0;
virtual uint32_t capacity() = 0;
};
}
}
#endif

View File

@ -13,7 +13,6 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Allocator.h"
@ -21,7 +20,7 @@
namespace llvm {
namespace codeview {
class TypeDatabase : public TypeCollection {
class TypeDatabase {
friend class RandomAccessTypeVisitor;
public:
@ -42,31 +41,19 @@ public:
CVType &getTypeRecord(TypeIndex Index);
bool contains(TypeIndex Index) const;
uint32_t size() const;
uint32_t capacity() const;
bool empty() const;
CVType getType(TypeIndex Index) override;
StringRef getTypeName(TypeIndex Index) override;
bool contains(TypeIndex Index) override;
uint32_t size() override;
uint32_t capacity() override;
TypeIndex getFirst() override;
Optional<TypeIndex> getNext(TypeIndex Prev) override;
Optional<TypeIndex> largestTypeIndexLessThan(TypeIndex TI) const;
private:
TypeIndex getAppendIndex() const;
private:
void grow();
void grow(TypeIndex Index);
BumpPtrAllocator Allocator;
uint32_t Count = 0;
TypeIndex LargestTypeIndex;
/// All user defined type records in .debug$T live in here. Type indices
/// greater than 0x1000 are user defined. Subtract 0x1000 from the index to

View File

@ -12,6 +12,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
@ -21,20 +22,17 @@ class ScopedPrinter;
namespace codeview {
class TypeCollection;
/// Dumper for CodeView type streams found in COFF object files and PDB files.
class TypeDumpVisitor : public TypeVisitorCallbacks {
public:
TypeDumpVisitor(TypeCollection &TpiTypes, ScopedPrinter *W,
bool PrintRecordBytes)
: W(W), PrintRecordBytes(PrintRecordBytes), TpiTypes(TpiTypes) {}
TypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W, bool PrintRecordBytes)
: W(W), PrintRecordBytes(PrintRecordBytes), TypeDB(TypeDB) {}
/// When dumping types from an IPI stream in a PDB, a type index may refer to
/// a type or an item ID. The dumper will lookup the "name" of the index in
/// the item database if appropriate. If ItemDB is null, it will use TypeDB,
/// which is correct when dumping types from an object file (/Z7).
void setIpiTypes(TypeCollection &Types) { IpiTypes = &Types; }
void setItemDB(TypeDatabase &DB) { ItemDB = &DB; }
void printTypeIndex(StringRef FieldName, TypeIndex TI) const;
@ -68,16 +66,14 @@ private:
/// Get the database of indices for the stream that we are dumping. If ItemDB
/// is set, then we must be dumping an item (IPI) stream. This will also
/// always get the appropriate DB for printing item names.
TypeCollection &getSourceTypes() const {
return IpiTypes ? *IpiTypes : TpiTypes;
}
TypeDatabase &getSourceDB() const { return ItemDB ? *ItemDB : TypeDB; }
ScopedPrinter *W;
bool PrintRecordBytes = false;
TypeCollection &TpiTypes;
TypeCollection *IpiTypes = nullptr;
TypeDatabase &TypeDB;
TypeDatabase *ItemDB = nullptr;
};
} // end namespace codeview

View File

@ -15,13 +15,8 @@
#include <cinttypes>
namespace llvm {
class ScopedPrinter;
namespace codeview {
class TypeCollection;
enum class SimpleTypeKind : uint32_t {
None = 0x0000, // uncharacterized type (no type)
Void = 0x0003, // void
@ -243,11 +238,6 @@ public:
return Result;
}
friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) {
assert(A >= B);
return A.toArrayIndex() - B.toArrayIndex();
}
private:
support::ulittle32_t Index;
};
@ -259,9 +249,6 @@ struct TypeIndexOffset {
TypeIndex Type;
support::ulittle32_t Offset;
};
void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI,
TypeCollection &Types);
}
}

View File

@ -1,42 +0,0 @@
//===- TypeTableCollection.h ---------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
namespace llvm {
namespace codeview {
class TypeTableCollection : public TypeCollection {
public:
explicit TypeTableCollection(ArrayRef<MutableArrayRef<uint8_t>> Records);
TypeIndex getFirst() override;
Optional<TypeIndex> getNext(TypeIndex Prev) override;
CVType getType(TypeIndex Index) override;
StringRef getTypeName(TypeIndex Index) override;
bool contains(TypeIndex Index) override;
uint32_t size() override;
uint32_t capacity() override;
private:
bool hasCapacityFor(TypeIndex Index) const;
void ensureTypeExists(TypeIndex Index);
ArrayRef<MutableArrayRef<uint8_t>> Records;
TypeDatabase Database;
};
}
}
#endif

View File

@ -17,6 +17,8 @@ namespace llvm {
namespace codeview {
class TypeVisitorCallbacks {
friend class CVTypeVisitor;
public:
virtual ~TypeVisitorCallbacks() = default;

View File

@ -13,6 +13,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"

View File

@ -13,6 +13,7 @@
#include "CodeViewDebug.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
@ -22,7 +23,6 @@
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/IR/Constants.h"
#include "llvm/MC/MCAsmInfo.h"
@ -469,21 +469,17 @@ void CodeViewDebug::emitTypeInformation() {
CommentPrefix += ' ';
}
TypeTableCollection Table(TypeTable.records());
Optional<TypeIndex> B = Table.getFirst();
do {
// This will fail if the record data is invalid.
CVType Record = Table.getType(*B);
TypeDatabase TypeDB(TypeTable.records().size());
CVTypeDumper CVTD(TypeDB);
TypeTable.ForEachRecord([&](TypeIndex Index, ArrayRef<uint8_t> Record) {
if (OS.isVerboseAsm()) {
// Emit a block comment describing the type record for readability.
SmallString<512> CommentBlock;
raw_svector_ostream CommentOS(CommentBlock);
ScopedPrinter SP(CommentOS);
SP.setPrefix(CommentPrefix);
TypeDumpVisitor TDV(Table, &SP, false);
Error E = codeview::visitTypeRecord(Record, *B, TDV);
TypeDumpVisitor TDV(TypeDB, &SP, false);
Error E = CVTD.dump(Record, TDV);
if (E) {
logAllUnhandledErrors(std::move(E), errs(), "error: ");
llvm_unreachable("produced malformed type record");
@ -493,9 +489,29 @@ void CodeViewDebug::emitTypeInformation() {
// newline.
OS.emitRawComment(
CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim());
} else {
#ifndef NDEBUG
// Assert that the type data is valid even if we aren't dumping
// comments. The MSVC linker doesn't do much type record validation,
// so the first link of an invalid type record can succeed while
// subsequent links will fail with LNK1285.
BinaryByteStream Stream(Record, llvm::support::little);
CVTypeArray Types;
BinaryStreamReader Reader(Stream);
Error E = Reader.readArray(Types, Reader.getLength());
if (!E) {
TypeVisitorCallbacks C;
E = codeview::visitTypeStream(Types, C);
}
if (E) {
logAllUnhandledErrors(std::move(E), errs(), "error: ");
llvm_unreachable("produced malformed type record");
}
#endif
}
OS.EmitBinaryData(Record.str_data());
} while ((B = Table.getNext(*B)));
StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size());
OS.EmitBinaryData(S);
});
}
namespace {

View File

@ -2,10 +2,10 @@ add_llvm_library(LLVMDebugInfoCodeView
CodeViewError.cpp
CodeViewRecordIO.cpp
CVSymbolVisitor.cpp
CVTypeDumper.cpp
CVTypeVisitor.cpp
EnumTables.cpp
Formatters.cpp
LazyRandomTypeCollection.cpp
Line.cpp
ModuleDebugFileChecksumFragment.cpp
ModuleDebugFragment.cpp
@ -13,6 +13,7 @@ add_llvm_library(LLVMDebugInfoCodeView
ModuleDebugFragmentVisitor.cpp
ModuleDebugInlineeLinesFragment.cpp
ModuleDebugLineFragment.cpp
RandomAccessTypeVisitor.cpp
RecordSerialization.cpp
StringTable.cpp
SymbolRecordMapping.cpp
@ -21,12 +22,10 @@ add_llvm_library(LLVMDebugInfoCodeView
TypeDatabase.cpp
TypeDatabaseVisitor.cpp
TypeDumpVisitor.cpp
TypeIndex.cpp
TypeRecordMapping.cpp
TypeSerializer.cpp
TypeStreamMerger.cpp
TypeTableCollection.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView
)

View File

@ -0,0 +1,61 @@
//===-- CVTypeDumper.cpp - CodeView type info dumper ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/Support/BinaryByteStream.h"
using namespace llvm;
using namespace llvm::codeview;
Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) {
TypeDatabaseVisitor DBV(TypeDB);
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(DBV);
Pipeline.addCallbackToPipeline(Dumper);
CVType RecordCopy = Record;
return codeview::visitTypeRecord(RecordCopy, Pipeline, VDS_BytesPresent,
Handler);
}
Error CVTypeDumper::dump(const CVTypeArray &Types,
TypeVisitorCallbacks &Dumper) {
TypeDatabaseVisitor DBV(TypeDB);
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(DBV);
Pipeline.addCallbackToPipeline(Dumper);
return codeview::visitTypeStream(Types, Pipeline, Handler);
}
Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) {
BinaryByteStream Stream(Data, llvm::support::little);
CVTypeArray Types;
BinaryStreamReader Reader(Stream);
if (auto EC = Reader.readArray(Types, Reader.getLength()))
return EC;
return dump(Types, Dumper);
}
void CVTypeDumper::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
TypeIndex TI, TypeDatabase &DB) {
StringRef TypeName;
if (!TI.isNoneType())
TypeName = DB.getTypeName(TI);
if (!TypeName.empty())
Printer.printHex(FieldName, TypeName, TI.getIndex());
else
Printer.printHex(FieldName, TI.getIndex());
}

View File

@ -9,9 +9,7 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
@ -24,6 +22,8 @@
using namespace llvm;
using namespace llvm::codeview;
CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
: Callbacks(Callbacks) {}
template <typename T>
static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
@ -66,67 +66,6 @@ static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) {
return R;
}
static Error visitMemberRecord(CVMemberRecord &Record,
TypeVisitorCallbacks &Callbacks) {
if (auto EC = Callbacks.visitMemberBegin(Record))
return EC;
switch (Record.Kind) {
default:
if (auto EC = Callbacks.visitUnknownMember(Record))
return EC;
break;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
return EC; \
break; \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
MEMBER_RECORD(EnumVal, EnumVal, AliasName)
#define TYPE_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
if (auto EC = Callbacks.visitMemberEnd(Record))
return EC;
return Error::success();
}
namespace {
class CVTypeVisitor {
public:
explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
void addTypeServerHandler(TypeServerHandler &Handler);
Error visitTypeRecord(CVType &Record, TypeIndex Index);
Error visitTypeRecord(CVType &Record);
/// Visits the type records in Data. Sets the error flag on parse failures.
Error visitTypeStream(const CVTypeArray &Types);
Error visitTypeStream(CVTypeRange Types);
Error visitTypeStream(TypeCollection &Types);
Error visitMemberRecord(CVMemberRecord Record);
Error visitFieldListMemberStream(BinaryStreamReader &Stream);
private:
Expected<bool> handleTypeServer(CVType &Record);
Error finishVisitation(CVType &Record);
/// The interface to the class that gets notified of each visitation.
TypeVisitorCallbacks &Callbacks;
TinyPtrVector<TypeServerHandler *> Handlers;
};
CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
: Callbacks(Callbacks) {}
void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) {
Handlers.push_back(&Handler);
}
@ -205,6 +144,35 @@ Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
return finishVisitation(Record);
}
static Error visitMemberRecord(CVMemberRecord &Record,
TypeVisitorCallbacks &Callbacks) {
if (auto EC = Callbacks.visitMemberBegin(Record))
return EC;
switch (Record.Kind) {
default:
if (auto EC = Callbacks.visitUnknownMember(Record))
return EC;
break;
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
case EnumName: { \
if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks)) \
return EC; \
break; \
}
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
MEMBER_RECORD(EnumVal, EnumVal, AliasName)
#define TYPE_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
if (auto EC = Callbacks.visitMemberEnd(Record))
return EC;
return Error::success();
}
Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
return ::visitMemberRecord(Record, Callbacks);
}
@ -226,20 +194,12 @@ Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
return Error::success();
}
Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
if (Types.empty())
return Error::success();
Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader Reader) {
FieldListDeserializer Deserializer(Reader);
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Callbacks);
Optional<TypeIndex> I = Types.getFirst();
do {
CVType Type = Types.getType(*I);
if (auto EC = visitTypeRecord(Type, *I))
return EC;
} while ((I = Types.getNext(*I)));
return Error::success();
}
Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
TypeLeafKind Leaf;
while (!Reader.empty()) {
if (auto EC = Reader.readEnum(Leaf))
@ -247,13 +207,20 @@ Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
CVMemberRecord Record;
Record.Kind = Leaf;
if (auto EC = ::visitMemberRecord(Record, Callbacks))
if (auto EC = ::visitMemberRecord(Record, Pipeline))
return EC;
}
return Error::success();
}
Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
BinaryByteStream S(Data, llvm::support::little);
BinaryStreamReader SR(S);
return visitFieldListMemberStream(SR);
}
namespace {
struct FieldListVisitHelper {
FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
VisitorDataSource Source)
@ -274,8 +241,11 @@ struct FieldListVisitHelper {
};
struct VisitHelper {
VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source,
TypeServerHandler *TS)
: Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
if (TS)
Visitor.addTypeServerHandler(*TS);
if (Source == VDS_BytesPresent) {
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Callbacks);
@ -292,57 +262,29 @@ Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source,
TypeServerHandler *TS) {
VisitHelper V(Callbacks, Source);
if (TS)
V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeRecord(Record, Index);
VisitHelper Helper(Callbacks, Source, TS);
return Helper.Visitor.visitTypeRecord(Record, Index);
}
Error llvm::codeview::visitTypeRecord(CVType &Record,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source,
TypeServerHandler *TS) {
VisitHelper V(Callbacks, Source);
if (TS)
V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeRecord(Record);
VisitHelper Helper(Callbacks, Source, TS);
return Helper.Visitor.visitTypeRecord(Record);
}
Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS) {
VisitHelper V(Callbacks, VDS_BytesPresent);
if (TS)
V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeStream(Types);
}
Error llvm::codeview::visitTypeStream(CVTypeRange Types,
TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS) {
VisitHelper V(Callbacks, VDS_BytesPresent);
if (TS)
V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeStream(Types);
}
Error llvm::codeview::visitTypeStream(TypeCollection &Types,
TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS) {
// When the internal visitor calls Types.getType(Index) the interface is
// required to return a CVType with the bytes filled out. So we can assume
// that the bytes will be present when individual records are visited.
VisitHelper V(Callbacks, VDS_BytesPresent);
if (TS)
V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeStream(Types);
Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
TypeVisitorCallbacks &Callbacks) {
CVTypeVisitor Visitor(Callbacks);
return Visitor.visitFieldListMemberStream(FieldList);
}
Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source) {
FieldListVisitHelper V(Callbacks, Record.Data, Source);
return V.Visitor.visitMemberRecord(Record);
FieldListVisitHelper Helper(Callbacks, Record.Data, Source);
return Helper.Visitor.visitMemberRecord(Record);
}
Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
@ -354,8 +296,16 @@ Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
}
Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
TypeVisitorCallbacks &Callbacks) {
FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
return V.Visitor.visitFieldListMemberStream(V.Reader);
Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS) {
VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
return Helper.Visitor.visitTypeStream(Types);
}
Error llvm::codeview::visitTypeStream(CVTypeRange Types,
TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS) {
VisitHelper Helper(Callbacks, VDS_BytesPresent, TS);
return Helper.Visitor.visitTypeStream(Types);
}

View File

@ -1,226 +0,0 @@
//===- LazyRandomTypeCollection.cpp ---------------------------- *- C++--*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
using namespace llvm;
using namespace llvm::codeview;
static void error(Error &&EC) {
assert(!static_cast<bool>(EC));
if (EC)
consumeError(std::move(EC));
}
LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint)
: LazyRandomTypeCollection(CVTypeArray(), RecordCountHint,
PartialOffsetArray()) {}
LazyRandomTypeCollection::LazyRandomTypeCollection(
const CVTypeArray &Types, uint32_t RecordCountHint,
PartialOffsetArray PartialOffsets)
: Database(RecordCountHint), Types(Types), DatabaseVisitor(Database),
PartialOffsets(PartialOffsets) {
KnownOffsets.resize(Database.capacity());
}
LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef<uint8_t> Data,
uint32_t RecordCountHint)
: LazyRandomTypeCollection(RecordCountHint) {
reset(Data);
}
LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data,
uint32_t RecordCountHint)
: LazyRandomTypeCollection(
makeArrayRef(Data.bytes_begin(), Data.bytes_end()), RecordCountHint) {
}
LazyRandomTypeCollection::LazyRandomTypeCollection(const CVTypeArray &Types,
uint32_t NumRecords)
: LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {}
void LazyRandomTypeCollection::reset(StringRef Data) {
reset(makeArrayRef(Data.bytes_begin(), Data.bytes_end()));
}
void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data) {
PartialOffsets = PartialOffsetArray();
BinaryStreamReader Reader(Data, support::little);
error(Reader.readArray(Types, Reader.getLength()));
KnownOffsets.resize(Database.capacity());
}
CVType LazyRandomTypeCollection::getType(TypeIndex Index) {
error(ensureTypeExists(Index));
return Database.getTypeRecord(Index);
}
StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) {
if (!Index.isSimple()) {
// Try to make sure the type exists. Even if it doesn't though, it may be
// because we're dumping a symbol stream with no corresponding type stream
// present, in which case we still want to be able to print <unknown UDT>
// for the type names.
consumeError(ensureTypeExists(Index));
}
return Database.getTypeName(Index);
}
bool LazyRandomTypeCollection::contains(TypeIndex Index) {
return Database.contains(Index);
}
uint32_t LazyRandomTypeCollection::size() { return Database.size(); }
uint32_t LazyRandomTypeCollection::capacity() { return Database.capacity(); }
Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) {
if (!Database.contains(TI)) {
if (auto EC = visitRangeForType(TI))
return EC;
}
return Error::success();
}
Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {
if (PartialOffsets.empty())
return fullScanForType(TI);
auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI,
[](TypeIndex Value, const TypeIndexOffset &IO) {
return Value < IO.Type;
});
assert(Next != PartialOffsets.begin());
auto Prev = std::prev(Next);
TypeIndex TIB = Prev->Type;
if (Database.contains(TIB)) {
// They've asked us to fetch a type index, but the entry we found in the
// partial offsets array has already been visited. Since we visit an entire
// block every time, that means this record should have been previously
// discovered. Ultimately, this means this is a request for a non-existant
// type index.
return make_error<CodeViewError>("Invalid type index");
}
TypeIndex TIE;
if (Next == PartialOffsets.end()) {
TIE = TypeIndex::fromArrayIndex(Database.capacity());
} else {
TIE = Next->Type;
}
if (auto EC = visitRange(TIB, Prev->Offset, TIE))
return EC;
return Error::success();
}
TypeIndex LazyRandomTypeCollection::getFirst() {
TypeIndex TI = TypeIndex::fromArrayIndex(0);
error(ensureTypeExists(TI));
return TI;
}
Optional<TypeIndex> LazyRandomTypeCollection::getNext(TypeIndex Prev) {
// We can't be sure how long this type stream is, given that the initial count
// given to the constructor is just a hint. So just try to make sure the next
// record exists, and if anything goes wrong, we must be at the end.
if (auto EC = ensureTypeExists(Prev + 1)) {
consumeError(std::move(EC));
return None;
}
return Prev + 1;
}
Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {
assert(PartialOffsets.empty());
TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0);
uint32_t Offset = 0;
auto Begin = Types.begin();
if (!Database.empty()) {
// In the case of type streams which we don't know the number of records of,
// it's possible to search for a type index triggering a full scan, but then
// later additional records are added since we didn't know how many there
// would be until we did a full visitation, then you try to access the new
// type triggering another full scan. To avoid this, we assume that if the
// database has some records, this must be what's going on. So we ask the
// database for the largest type index less than the one we're searching for
// and only do the forward scan from there.
auto Prev = Database.largestTypeIndexLessThan(TI);
assert(Prev.hasValue() && "Empty database with valid types?");
Offset = KnownOffsets[Prev->toArrayIndex()];
CurrentTI = *Prev;
++CurrentTI;
Begin = Types.at(Offset);
++Begin;
Offset = Begin.offset();
}
auto End = Types.end();
while (Begin != End) {
if (auto EC = visitOneRecord(CurrentTI, Offset, *Begin))
return EC;
Offset += Begin.getRecordLength();
++Begin;
++CurrentTI;
}
if (CurrentTI <= TI) {
return make_error<CodeViewError>("Type Index does not exist!");
}
return Error::success();
}
Error LazyRandomTypeCollection::visitRange(TypeIndex Begin,
uint32_t BeginOffset,
TypeIndex End) {
auto RI = Types.at(BeginOffset);
assert(RI != Types.end());
while (Begin != End) {
if (auto EC = visitOneRecord(Begin, BeginOffset, *RI))
return EC;
BeginOffset += RI.getRecordLength();
++Begin;
++RI;
}
return Error::success();
}
Error LazyRandomTypeCollection::visitOneRecord(TypeIndex TI, uint32_t Offset,
CVType &Record) {
assert(!Database.contains(TI));
if (auto EC = codeview::visitTypeRecord(Record, TI, DatabaseVisitor))
return EC;
// Keep the KnownOffsets array the same size as the Database's capacity. Since
// we don't always know how many records are in the type stream, we need to be
// prepared for the database growing and receicing a type index that can't fit
// in our current buffer.
if (KnownOffsets.size() < Database.capacity())
KnownOffsets.resize(Database.capacity());
KnownOffsets[TI.toArrayIndex()] = Offset;
return Error::success();
}

View File

@ -0,0 +1,89 @@
//===- RandomAccessTypeVisitor.cpp ---------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
using namespace llvm;
using namespace llvm::codeview;
RandomAccessTypeVisitor::RandomAccessTypeVisitor(
const CVTypeArray &Types, uint32_t NumRecords,
PartialOffsetArray PartialOffsets)
: Database(NumRecords), Types(Types), DatabaseVisitor(Database),
PartialOffsets(PartialOffsets) {
KnownOffsets.resize(Database.capacity());
}
Error RandomAccessTypeVisitor::visitTypeIndex(TypeIndex TI,
TypeVisitorCallbacks &Callbacks) {
assert(TI.toArrayIndex() < Database.capacity());
if (!Database.contains(TI)) {
if (auto EC = visitRangeForType(TI))
return EC;
}
assert(Database.contains(TI));
auto &Record = Database.getTypeRecord(TI);
return codeview::visitTypeRecord(Record, TI, Callbacks);
}
Error RandomAccessTypeVisitor::visitRangeForType(TypeIndex TI) {
if (PartialOffsets.empty()) {
TypeIndex TIB(TypeIndex::FirstNonSimpleIndex);
TypeIndex TIE = TIB + Database.capacity();
return visitRange(TIB, 0, TIE);
}
auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI,
[](TypeIndex Value, const TypeIndexOffset &IO) {
return Value < IO.Type;
});
assert(Next != PartialOffsets.begin());
auto Prev = std::prev(Next);
TypeIndex TIB = Prev->Type;
TypeIndex TIE;
if (Next == PartialOffsets.end()) {
TIE = TypeIndex::fromArrayIndex(Database.capacity());
} else {
TIE = Next->Type;
}
if (auto EC = visitRange(TIB, Prev->Offset, TIE))
return EC;
return Error::success();
}
Error RandomAccessTypeVisitor::visitRange(TypeIndex Begin, uint32_t BeginOffset,
TypeIndex End) {
auto RI = Types.at(BeginOffset);
assert(RI != Types.end());
while (Begin != End) {
assert(!Database.contains(Begin));
if (auto EC = codeview::visitTypeRecord(*RI, Begin, DatabaseVisitor))
return EC;
KnownOffsets[Begin.toArrayIndex()] = BeginOffset;
BeginOffset += RI.getRecordLength();
++Begin;
++RI;
}
return Error::success();
}

View File

@ -11,6 +11,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/StringTable.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
@ -32,9 +33,9 @@ namespace {
/// the visitor out of SymbolDumper.h.
class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
public:
CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate,
CVSymbolDumperImpl(TypeDatabase &TypeDB, SymbolDumpDelegate *ObjDelegate,
ScopedPrinter &W, bool PrintRecordBytes)
: Types(Types), ObjDelegate(ObjDelegate), W(W),
: TypeDB(TypeDB), ObjDelegate(ObjDelegate), W(W),
PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
/// CVSymbolVisitor overrides.
@ -53,7 +54,7 @@ private:
void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
void printTypeIndex(StringRef FieldName, TypeIndex TI);
TypeCollection &Types;
TypeDatabase &TypeDB;
SymbolDumpDelegate *ObjDelegate;
ScopedPrinter &W;
@ -82,7 +83,7 @@ void CVSymbolDumperImpl::printLocalVariableAddrGap(
}
void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) {
codeview::printTypeIndex(W, FieldName, TI, Types);
CVTypeDumper::printTypeIndex(W, FieldName, TI, TypeDB);
}
Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
@ -669,7 +670,7 @@ Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
SymbolVisitorCallbackPipeline Pipeline;
SymbolDeserializer Deserializer(ObjDelegate.get());
CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
@ -680,7 +681,7 @@ Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
SymbolVisitorCallbackPipeline Pipeline;
SymbolDeserializer Deserializer(ObjDelegate.get());
CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes);
CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);

View File

@ -72,20 +72,16 @@ TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) {
}
TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) {
LargestTypeIndex = getAppendIndex();
if (LargestTypeIndex.toArrayIndex() >= capacity())
TypeIndex TI;
TI = getAppendIndex();
if (TI.toArrayIndex() >= capacity())
grow();
recordType(Name, LargestTypeIndex, Data);
return LargestTypeIndex;
recordType(Name, TI, Data);
return TI;
}
void TypeDatabase::recordType(StringRef Name, TypeIndex Index,
const CVType &Data) {
LargestTypeIndex = empty() ? Index : std::max(Index, LargestTypeIndex);
if (LargestTypeIndex.toArrayIndex() >= capacity())
grow(Index);
uint32_t AI = Index.toArrayIndex();
assert(!contains(Index));
@ -148,65 +144,19 @@ uint32_t TypeDatabase::size() const { return Count; }
uint32_t TypeDatabase::capacity() const { return TypeRecords.size(); }
CVType TypeDatabase::getType(TypeIndex Index) { return getTypeRecord(Index); }
StringRef TypeDatabase::getTypeName(TypeIndex Index) {
return static_cast<const TypeDatabase *>(this)->getTypeName(Index);
}
bool TypeDatabase::contains(TypeIndex Index) {
return static_cast<const TypeDatabase *>(this)->contains(Index);
}
uint32_t TypeDatabase::size() {
return static_cast<const TypeDatabase *>(this)->size();
}
uint32_t TypeDatabase::capacity() {
return static_cast<const TypeDatabase *>(this)->capacity();
}
void TypeDatabase::grow() { grow(LargestTypeIndex + 1); }
void TypeDatabase::grow(TypeIndex NewIndex) {
uint32_t NewSize = NewIndex.toArrayIndex() + 1;
if (NewSize <= capacity())
return;
uint32_t NewCapacity = NewSize * 3 / 2;
TypeRecords.resize(NewCapacity);
CVUDTNames.resize(NewCapacity);
ValidRecords.resize(NewCapacity);
void TypeDatabase::grow() {
TypeRecords.emplace_back();
CVUDTNames.emplace_back();
ValidRecords.resize(ValidRecords.size() + 1);
}
bool TypeDatabase::empty() const { return size() == 0; }
Optional<TypeIndex> TypeDatabase::largestTypeIndexLessThan(TypeIndex TI) const {
uint32_t AI = TI.toArrayIndex();
int N = ValidRecords.find_prev(AI);
if (N == -1)
return None;
return TypeIndex::fromArrayIndex(N);
}
TypeIndex TypeDatabase::getAppendIndex() const {
if (empty())
return TypeIndex::fromArrayIndex(0);
return LargestTypeIndex + 1;
}
TypeIndex TypeDatabase::getFirst() {
int N = ValidRecords.find_first();
assert(N != -1);
return TypeIndex::fromArrayIndex(N);
}
Optional<TypeIndex> TypeDatabase::getNext(TypeIndex Prev) {
int N = ValidRecords.find_next(Prev.toArrayIndex());
if (N == -1)
return None;
return TypeIndex::fromArrayIndex(N);
int Index = ValidRecords.find_last();
assert(Index != -1);
return TypeIndex::fromArrayIndex(Index) + 1;
}

View File

@ -10,13 +10,15 @@
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/Formatters.h"
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ScopedPrinter.h"
@ -163,15 +165,16 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
}
void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
codeview::printTypeIndex(*W, FieldName, TI, TpiTypes);
CVTypeDumper::printTypeIndex(*W, FieldName, TI, TypeDB);
}
void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const {
codeview::printTypeIndex(*W, FieldName, TI, getSourceTypes());
CVTypeDumper::printTypeIndex(*W, FieldName, TI, getSourceDB());
}
Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
return visitTypeBegin(Record, TypeIndex::fromArrayIndex(TpiTypes.size()));
TypeIndex TI = getSourceDB().getAppendIndex();
return visitTypeBegin(Record, TI);
}
Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
@ -242,7 +245,7 @@ Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringListRecord &Strs) {
W->printNumber("NumStrings", Size);
ListScope Arguments(*W, "Strings");
for (uint32_t I = 0; I < Size; ++I) {
printItemIndex("String", Indices[I]);
printTypeIndex("String", Indices[I]);
}
return Error::success();
}

View File

@ -1,27 +0,0 @@
//===-- TypeIndex.cpp - CodeView type index ---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/Support/ScopedPrinter.h"
using namespace llvm;
using namespace llvm::codeview;
void llvm::codeview::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
TypeIndex TI, TypeCollection &Types) {
StringRef TypeName;
if (!TI.isNoneType())
TypeName = Types.getTypeName(TI);
if (!TypeName.empty())
Printer.printHex(FieldName, TypeName, TI.getIndex());
else
Printer.printHex(FieldName, TI.getIndex());
}

View File

@ -11,9 +11,11 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"

View File

@ -1,82 +0,0 @@
//===- TypeTableCollection.cpp -------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
using namespace llvm;
using namespace llvm::codeview;
static void error(Error &&EC) {
assert(!static_cast<bool>(EC));
if (EC)
consumeError(std::move(EC));
}
TypeTableCollection::TypeTableCollection(
ArrayRef<MutableArrayRef<uint8_t>> Records)
: Records(Records), Database(Records.size()) {}
TypeIndex TypeTableCollection::getFirst() {
assert(!empty());
return TypeIndex::fromArrayIndex(0);
}
Optional<TypeIndex> TypeTableCollection::getNext(TypeIndex Prev) {
++Prev;
assert(Prev.toArrayIndex() <= size());
if (Prev.toArrayIndex() == size())
return None;
return Prev;
}
void TypeTableCollection::ensureTypeExists(TypeIndex Index) {
assert(hasCapacityFor(Index));
if (Database.contains(Index))
return;
BinaryByteStream Bytes(Records[Index.toArrayIndex()], support::little);
CVType Type;
uint32_t Len;
error(VarStreamArrayExtractor<CVType>::extract(Bytes, Len, Type));
TypeDatabaseVisitor DBV(Database);
error(codeview::visitTypeRecord(Type, Index, DBV));
assert(Database.contains(Index));
}
CVType TypeTableCollection::getType(TypeIndex Index) {
ensureTypeExists(Index);
return Database.getTypeRecord(Index);
}
StringRef TypeTableCollection::getTypeName(TypeIndex Index) {
if (!Index.isSimple())
ensureTypeExists(Index);
return Database.getTypeName(Index);
}
bool TypeTableCollection::contains(TypeIndex Index) {
return Database.contains(Index);
}
uint32_t TypeTableCollection::size() { return Records.size(); }
uint32_t TypeTableCollection::capacity() { return Records.size(); }
bool TypeTableCollection::hasCapacityFor(TypeIndex Index) const {
return Index.toArrayIndex() < Records.size();
}

View File

@ -21,7 +21,6 @@
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"

View File

@ -9,7 +9,10 @@
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"

View File

@ -326,7 +326,7 @@
; EMPTY-NEXT: TypeLeafKind: LF_SUBSTR_LIST (0x1604)
; EMPTY-NEXT: NumStrings: 1
; EMPTY-NEXT: Strings [
; EMPTY-NEXT: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows
; EMPTY-NEXT: String: __vc_attributes::threadingAttribute (0x100B)
; EMPTY-NEXT: ]
; EMPTY-NEXT: }
; EMPTY-NEXT: Bytes (
@ -1253,7 +1253,7 @@
; ALL: TypeLeafKind: LF_SUBSTR_LIST (0x1604)
; ALL: NumStrings: 1
; ALL: Strings [
; ALL: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows (0x100B)
; ALL: String: __vc_attributes::threadingAttribute (0x100B)
; ALL: ]
; ALL: }
; ALL: }

View File

@ -14,6 +14,7 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"

View File

@ -29,15 +29,15 @@ static StringRef getLeafName(TypeLeafKind K) {
return StringRef();
}
CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
ScopedPrinter *W)
: CompactTypeDumpVisitor(Types, TypeIndex(TypeIndex::FirstNonSimpleIndex),
: CompactTypeDumpVisitor(TypeDB, TypeIndex(TypeIndex::FirstNonSimpleIndex),
W) {}
CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
TypeIndex FirstTI,
ScopedPrinter *W)
: W(W), TI(FirstTI), Offset(0), Types(Types) {}
: W(W), TI(FirstTI), Offset(0), TypeDB(TypeDB) {}
Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
return Error::success();
@ -46,7 +46,7 @@ Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) {
uint32_t I = TI.getIndex();
StringRef Leaf = getLeafName(Record.Type);
StringRef Name = Types.getTypeName(TI);
StringRef Name = TypeDB.getTypeName(TI);
W->printString(
llvm::formatv("Index: {0:x} ({1:N} bytes, offset {2:N}) {3} \"{4}\"", I,
Record.length(), Offset, Leaf, Name)

View File

@ -17,7 +17,7 @@
namespace llvm {
class ScopedPrinter;
namespace codeview {
class TypeCollection;
class TypeDatabase;
}
namespace pdb {
@ -26,8 +26,8 @@ namespace pdb {
/// Dumps records on a single line, and ignores member records.
class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
public:
CompactTypeDumpVisitor(codeview::TypeCollection &Types, ScopedPrinter *W);
CompactTypeDumpVisitor(codeview::TypeCollection &Types,
CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, ScopedPrinter *W);
CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB,
codeview::TypeIndex FirstTI, ScopedPrinter *W);
/// Paired begin/end actions for all types. Receives all record data,
@ -40,7 +40,7 @@ private:
codeview::TypeIndex TI;
uint32_t Offset;
codeview::TypeCollection &Types;
codeview::TypeDatabase &TypeDB;
};
} // end namespace pdb

View File

@ -14,9 +14,9 @@
#include "StreamUtil.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h"
@ -25,6 +25,7 @@
#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
@ -83,7 +84,7 @@ struct PageStats {
class C13RawVisitor : public C13DebugFragmentVisitor {
public:
C13RawVisitor(ScopedPrinter &P, PDBFile &F, LazyRandomTypeCollection &IPI)
C13RawVisitor(ScopedPrinter &P, PDBFile &F, TypeDatabase &IPI)
: C13DebugFragmentVisitor(F), P(P), IPI(IPI) {}
Error handleLines() override {
@ -159,7 +160,7 @@ public:
if (auto EC = printFileName("FileName", L.Header->FileID))
return EC;
if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee))
if (auto EC = dumpTypeRecord("Function", IPI, L.Header->Inlinee))
return EC;
P.printNumber("SourceLine", L.Header->SourceLineNum);
if (IL.hasExtraFiles()) {
@ -175,11 +176,11 @@ public:
}
private:
Error dumpTypeRecord(StringRef Label, TypeIndex Index) {
CompactTypeDumpVisitor CTDV(IPI, Index, &P);
Error dumpTypeRecord(StringRef Label, TypeDatabase &DB, TypeIndex Index) {
CompactTypeDumpVisitor CTDV(DB, Index, &P);
DictScope D(P, Label);
if (IPI.contains(Index)) {
CVType Type = IPI.getType(Index);
if (DB.contains(Index)) {
CVType &Type = DB.getTypeRecord(Index);
if (auto EC = codeview::visitTypeRecord(Type, CTDV))
return EC;
} else {
@ -198,7 +199,7 @@ private:
}
ScopedPrinter &P;
LazyRandomTypeCollection &IPI;
TypeDatabase &IPI;
};
}
@ -608,19 +609,14 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
VerLabel = "IPI Version";
}
if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
return Error::success();
auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
: File.getPDBIpiStream();
if (!Tpi)
return Tpi.takeError();
auto ExpectedTypes = initializeTypeDatabase(StreamIdx);
if (!ExpectedTypes)
return ExpectedTypes.takeError();
auto &Types = *ExpectedTypes;
if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
return Error::success();
std::unique_ptr<DictScope> StreamScope;
std::unique_ptr<ListScope> RecordScope;
@ -628,19 +624,25 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
P.printNumber(VerLabel, Tpi->getTpiVersion());
P.printNumber("Record count", Tpi->getNumTypeRecords());
Optional<TypeDatabase> &StreamDB = (StreamIdx == StreamTPI) ? TypeDB : ItemDB;
std::vector<std::unique_ptr<TypeVisitorCallbacks>> Visitors;
if (!StreamDB.hasValue()) {
StreamDB.emplace(Tpi->getNumTypeRecords());
Visitors.push_back(make_unique<TypeDatabaseVisitor>(*StreamDB));
}
// If we're in dump mode, add a dumper with the appropriate detail level.
if (DumpRecords) {
std::unique_ptr<TypeVisitorCallbacks> Dumper;
if (opts::raw::CompactRecords)
Dumper = make_unique<CompactTypeDumpVisitor>(Types, &P);
Dumper = make_unique<CompactTypeDumpVisitor>(*StreamDB, &P);
else {
assert(TpiTypes);
assert(TypeDB.hasValue());
auto X = make_unique<TypeDumpVisitor>(*TpiTypes, &P, false);
auto X = make_unique<TypeDumpVisitor>(*TypeDB, &P, false);
if (StreamIdx == StreamIPI)
X->setIpiTypes(*IpiTypes);
X->setItemDB(*ItemDB);
Dumper = std::move(X);
}
Visitors.push_back(std::move(Dumper));
@ -658,17 +660,23 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
if (DumpRecords || DumpRecordBytes)
RecordScope = llvm::make_unique<ListScope>(P, "Records");
Optional<TypeIndex> I = Types.getFirst();
do {
bool HadError = false;
TypeIndex T(TypeIndex::FirstNonSimpleIndex);
for (auto Type : Tpi->types(&HadError)) {
std::unique_ptr<DictScope> OneRecordScope;
if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords)
OneRecordScope = llvm::make_unique<DictScope>(P, "");
auto T = Types.getType(*I);
if (auto EC = codeview::visitTypeRecord(T, *I, Pipeline))
if (auto EC = codeview::visitTypeRecord(Type, Pipeline))
return EC;
} while ((I = Types.getNext(*I)));
++T;
}
if (HadError)
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI stream contained corrupt record");
if (DumpTpiHash) {
DictScope DD(P, "Hash");
@ -703,26 +711,35 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
return Error::success();
}
Expected<codeview::LazyRandomTypeCollection &>
LLVMOutputStyle::initializeTypeDatabase(uint32_t SN) {
auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
Error LLVMOutputStyle::buildTypeDatabase(uint32_t SN) {
assert(SN == StreamIPI || SN == StreamTPI);
auto &DB = (SN == StreamIPI) ? ItemDB : TypeDB;
if (DB.hasValue())
return Error::success();
auto Tpi =
(SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
if (!Tpi)
return Tpi.takeError();
if (!TypeCollection) {
// Initialize the type collection, even if we're not going to dump it. This
// way if some other part of the dumper decides it wants to use some or all
// of the records for whatever purposes, it can still access them lazily.
auto &Types = Tpi->typeArray();
uint32_t Count = Tpi->getNumTypeRecords();
auto Offsets = Tpi->getTypeIndexOffsets();
TypeCollection =
llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
}
DB.emplace(Tpi->getNumTypeRecords());
return *TypeCollection;
TypeDatabaseVisitor DBV(*DB);
auto HashValues = Tpi->getHashValues();
if (HashValues.empty())
return codeview::visitTypeStream(Tpi->typeArray(), DBV);
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(DBV);
TpiHashVerifier HashVerifier(HashValues, Tpi->getNumHashBuckets());
Pipeline.addCallbackToPipeline(HashVerifier);
return codeview::visitTypeStream(Tpi->typeArray(), Pipeline);
}
Error LLVMOutputStyle::dumpDbiStream() {
@ -797,13 +814,11 @@ Error LLVMOutputStyle::dumpDbiStream() {
return EC;
if (ShouldDumpSymbols) {
auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
if (!ExpectedTypes)
return ExpectedTypes.takeError();
auto &Types = *ExpectedTypes;
if (auto EC = buildTypeDatabase(StreamTPI))
return EC;
ListScope SS(P, "Symbols");
codeview::CVSymbolDumper SD(P, Types, nullptr, false);
codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false);
bool HadError = false;
for (auto S : ModS.symbols(&HadError)) {
DictScope LL(P, "");
@ -824,11 +839,10 @@ Error LLVMOutputStyle::dumpDbiStream() {
}
if (opts::raw::DumpLineInfo) {
ListScope SS(P, "LineInfo");
auto ExpectedTypes = initializeTypeDatabase(StreamIPI);
if (!ExpectedTypes)
return ExpectedTypes.takeError();
auto &IpiItems = *ExpectedTypes;
C13RawVisitor V(P, File, IpiItems);
if (auto EC = buildTypeDatabase(StreamIPI))
return EC;
C13RawVisitor V(P, File, *ItemDB);
if (auto EC = codeview::visitModuleDebugFragments(
ModS.linesAndChecksums(), V))
return EC;
@ -946,12 +960,10 @@ Error LLVMOutputStyle::dumpPublicsStream() {
P.printList("Section Offsets", Publics->getSectionOffsets(),
printSectionOffset);
ListScope L(P, "Symbols");
auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
if (!ExpectedTypes)
return ExpectedTypes.takeError();
auto &Tpi = *ExpectedTypes;
if (auto EC = buildTypeDatabase(StreamTPI))
return EC;
codeview::CVSymbolDumper SD(P, Tpi, nullptr, false);
codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false);
bool HadError = false;
for (auto S : Publics->getSymbols(&HadError)) {
DictScope DD(P, "");

View File

@ -21,11 +21,6 @@
namespace llvm {
class BitVector;
namespace codeview {
class LazyRandomTypeCollection;
}
namespace pdb {
class LLVMOutputStyle : public OutputStyle {
public:
@ -34,8 +29,7 @@ public:
Error dump() override;
private:
Expected<codeview::LazyRandomTypeCollection &>
initializeTypeDatabase(uint32_t SN);
Error buildTypeDatabase(uint32_t SN);
Error dumpFileHeaders();
Error dumpStreamSummary();
@ -60,8 +54,8 @@ private:
PDBFile &File;
ScopedPrinter P;
std::unique_ptr<codeview::LazyRandomTypeCollection> TpiTypes;
std::unique_ptr<codeview::LazyRandomTypeCollection> IpiTypes;
Optional<codeview::TypeDatabase> TypeDB;
Optional<codeview::TypeDatabase> ItemDB;
SmallVector<std::string, 32> StreamPurposes;
};
}

View File

@ -19,6 +19,7 @@
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
@ -370,6 +371,7 @@ void MappingContextTraits<PdbInlineeInfo, SerializationContext>::mapping(
void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>::
mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
pdb::yaml::SerializationContext &Context) {
if (IO.outputting()) {
// For PDB to Yaml, deserialize into a high level record type, then dump it.
consumeError(codeview::visitTypeRecord(Obj.Record, Context.Dumper));

View File

@ -13,6 +13,7 @@
#include "OutputStyle.h"
#include "PdbYaml.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/YAMLTraits.h"

View File

@ -13,6 +13,7 @@
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"

View File

@ -31,7 +31,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
@ -886,7 +885,7 @@ static void mergePdbs() {
DestIpi.addTypeRecord(Data, None);
});
SmallString<64> OutFile(opts::merge::PdbOutputFile);
SmallString<64> OutFile = opts::merge::PdbOutputFile;
if (OutFile.empty()) {
OutFile = opts::merge::InputFilenames[0];
llvm::sys::path::replace_extension(OutFile, "merged.pdb");

View File

@ -22,9 +22,8 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
@ -35,13 +34,11 @@
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/BinaryStreamReader.h"
@ -73,7 +70,7 @@ class COFFDumper : public ObjDumper {
public:
friend class COFFObjectDumpDelegate;
COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer)
: ObjDumper(Writer), Obj(Obj), Writer(Writer), Types(100) {}
: ObjDumper(Writer), Obj(Obj), Writer(Writer), TypeDB(100) {}
void printFileHeaders() override;
void printSections() override;
@ -109,7 +106,7 @@ private:
void printFileNameForOffset(StringRef Label, uint32_t FileOffset);
void printTypeIndex(StringRef FieldName, TypeIndex TI) {
// Forward to CVTypeDumper for simplicity.
codeview::printTypeIndex(Writer, FieldName, TI, Types);
CVTypeDumper::printTypeIndex(Writer, FieldName, TI, TypeDB);
}
void printCodeViewSymbolsSubsection(StringRef Subsection,
@ -162,8 +159,7 @@ private:
StringTableRef CVStringTable;
ScopedPrinter &Writer;
BinaryByteStream TypeContents;
LazyRandomTypeCollection Types;
TypeDatabase TypeDB;
};
class COFFObjectDumpDelegate : public SymbolDumpDelegate {
@ -979,7 +975,9 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
Subsection.bytes_end());
auto CODD = llvm::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj,
SectionContents);
CVSymbolDumper CVSD(W, Types, std::move(CODD), opts::CodeViewSubsectionBytes);
CVSymbolDumper CVSD(W, TypeDB, std::move(CODD),
opts::CodeViewSubsectionBytes);
CVSymbolArray Symbols;
BinaryStreamReader Reader(BinaryData, llvm::support::little);
if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
@ -1096,11 +1094,12 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
if (Magic != COFF::DEBUG_SECTION_MAGIC)
return error(object_error::parse_failed);
Types.reset(Data);
TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes);
error(codeview::visitTypeStream(Types, TDV));
W.flush();
CVTypeDumper CVTD(TypeDB);
TypeDumpVisitor TDV(TypeDB, &W, opts::CodeViewSubsectionBytes);
if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()}, TDV)) {
W.flush();
error(llvm::errorToErrorCode(std::move(EC)));
}
}
void COFFDumper::printSections() {
@ -1640,22 +1639,35 @@ void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer,
TypeBuf.append(Record.begin(), Record.end());
});
TypeTableCollection TpiTypes(CVTypes.records());
TypeDatabase TypeDB(CVTypes.records().size());
{
ListScope S(Writer, "MergedTypeStream");
TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);
error(codeview::visitTypeStream(TpiTypes, TDV));
Writer.flush();
CVTypeDumper CVTD(TypeDB);
TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
if (auto EC = CVTD.dump(
{TypeBuf.str().bytes_begin(), TypeBuf.str().bytes_end()}, TDV)) {
Writer.flush();
error(std::move(EC));
}
}
// Flatten the id stream and print it next. The ID stream refers to names from
// the type stream.
TypeTableCollection IpiTypes(IDTable.records());
SmallString<0> IDBuf;
IDTable.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Record) {
IDBuf.append(Record.begin(), Record.end());
});
{
ListScope S(Writer, "MergedIDStream");
TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);
TDV.setIpiTypes(IpiTypes);
error(codeview::visitTypeStream(IpiTypes, TDV));
Writer.flush();
TypeDatabase IDDB(IDTable.records().size());
CVTypeDumper CVTD(IDDB);
TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
TDV.setItemDB(IDDB);
if (auto EC = CVTD.dump(
{IDBuf.str().bytes_begin(), IDBuf.str().bytes_end()}, TDV)) {
Writer.flush();
error(std::move(EC));
}
}
}

View File

@ -11,12 +11,14 @@
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/Support/Allocator.h"
@ -128,16 +130,20 @@ public:
void SetUp() override {
TestState = llvm::make_unique<PerTestState>();
TestState->Pipeline.addCallbackToPipeline(TestState->Deserializer);
TestState->Pipeline.addCallbackToPipeline(TestState->Callbacks);
}
void TearDown() override { TestState.reset(); }
protected:
bool ValidateDatabaseRecord(LazyRandomTypeCollection &Types, uint32_t Index) {
bool ValidateDatabaseRecord(const RandomAccessTypeVisitor &Visitor,
uint32_t Index) {
TypeIndex TI = TypeIndex::fromArrayIndex(Index);
if (!Types.contains(TI))
if (!Visitor.database().contains(TI))
return false;
if (GlobalState->TypeVector[Index] != Types.getType(TI))
if (GlobalState->TypeVector[Index] != Visitor.database().getTypeRecord(TI))
return false;
return true;
}
@ -178,6 +184,8 @@ protected:
struct PerTestState {
FixedStreamArray<TypeIndexOffset> Offsets;
TypeVisitorCallbackPipeline Pipeline;
TypeDeserializer Deserializer;
MockCallbacks Callbacks;
};
@ -210,22 +218,21 @@ std::unique_ptr<RandomAccessVisitorTest::GlobalTestState>
TEST_F(RandomAccessVisitorTest, MultipleVisits) {
TestState->Offsets = createPartialOffsets(GlobalState->Stream, {0, 8});
LazyRandomTypeCollection Types(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
std::vector<uint32_t> IndicesToVisit = {5, 5, 5};
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
}
// [0,8) should be present
EXPECT_EQ(8u, Types.size());
EXPECT_EQ(8u, Visitor.database().size());
for (uint32_t I = 0; I < 8; ++I)
EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
// 5, 5, 5
EXPECT_EQ(3u, TestState->Callbacks.count());
@ -241,19 +248,19 @@ TEST_F(RandomAccessVisitorTest, DescendingWithinChunk) {
std::vector<uint32_t> IndicesToVisit = {7, 4, 2};
LazyRandomTypeCollection Types(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
}
// [0, 7]
EXPECT_EQ(8u, Types.size());
EXPECT_EQ(8u, Visitor.database().size());
for (uint32_t I = 0; I < 8; ++I)
EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
// 2, 4, 7
EXPECT_EQ(3u, TestState->Callbacks.count());
@ -269,19 +276,19 @@ TEST_F(RandomAccessVisitorTest, AscendingWithinChunk) {
std::vector<uint32_t> IndicesToVisit = {2, 4, 7};
LazyRandomTypeCollection Types(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
}
// [0, 7]
EXPECT_EQ(8u, Types.size());
EXPECT_EQ(8u, Visitor.database().size());
for (uint32_t I = 0; I < 8; ++I)
EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
// 2, 4, 7
EXPECT_EQ(3u, TestState->Callbacks.count());
@ -298,20 +305,19 @@ TEST_F(RandomAccessVisitorTest, StopPrematurelyInChunk) {
std::vector<uint32_t> IndicesToVisit = {0, 1, 2};
LazyRandomTypeCollection Types(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
}
// [0, 8) should be visited.
EXPECT_EQ(8u, Types.size());
EXPECT_EQ(8u, Visitor.database().size());
for (uint32_t I = 0; I < 8; ++I)
EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
// [0, 2]
EXPECT_EQ(3u, TestState->Callbacks.count());
@ -327,20 +333,19 @@ TEST_F(RandomAccessVisitorTest, InnerChunk) {
std::vector<uint32_t> IndicesToVisit = {5, 7};
LazyRandomTypeCollection Types(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
RandomAccessTypeVisitor Visitor(GlobalState->TypeArray,
GlobalState->TypeVector.size(),
TestState->Offsets);
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline));
}
// [4, 9)
EXPECT_EQ(5u, Types.size());
EXPECT_EQ(5u, Visitor.database().size());
for (uint32_t I = 4; I < 9; ++I)
EXPECT_TRUE(ValidateDatabaseRecord(Types, I));
EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I));
// 5, 7
EXPECT_EQ(2u, TestState->Callbacks.count());