summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo/CodeView
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2016-08-16 23:28:54 +0000
committerZachary Turner <zturner@google.com>2016-08-16 23:28:54 +0000
commit8321ba5437f7e35f37291473fc1bafc53d27c62f (patch)
tree5d60f9bcf99776b8f3215e25e764d518e2c5f6a7 /llvm/lib/DebugInfo/CodeView
parenta36f4a25b313ddddeceb77ebc2328e22ac4fdc5b (diff)
downloadbcm5719-llvm-8321ba5437f7e35f37291473fc1bafc53d27c62f.tar.gz
bcm5719-llvm-8321ba5437f7e35f37291473fc1bafc53d27c62f.zip
Write the TPI stream from a PDB to Yaml.
Reviewed By: ruiu, rnk Differential Revision: https://reviews.llvm.org/D23226 llvm-svn: 278869
Diffstat (limited to 'llvm/lib/DebugInfo/CodeView')
-rw-r--r--llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp87
-rw-r--r--llvm/lib/DebugInfo/CodeView/EnumTables.cpp10
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp68
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeDumper.cpp48
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeRecord.cpp9
-rw-r--r--llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp14
6 files changed, 144 insertions, 92 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index 1b96b0cb947..23e42e1468f 100644
--- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -15,6 +15,52 @@
using namespace llvm;
using namespace llvm::codeview;
+template <typename T>
+static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
+ if (Data.size() < sizeof(*Res))
+ return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+ Res = reinterpret_cast<const T *>(Data.data());
+ Data = Data.drop_front(sizeof(*Res));
+ return Error::success();
+}
+
+template <typename T>
+static Expected<CVType> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
+ TypeLeafKind Kind) {
+ ArrayRef<uint8_t> OldData = Data;
+ TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
+ auto ExpectedRecord = T::deserialize(RK, Data);
+ if (!ExpectedRecord)
+ return ExpectedRecord.takeError();
+ assert(Data.size() < OldData.size());
+ if (auto EC = skipPadding(Data))
+ return std::move(EC);
+
+ CVType CVR;
+ CVR.Type = Kind;
+ CVR.Length = OldData.size() - Data.size();
+ CVR.Data = OldData.slice(0, CVR.Length);
+ CVR.RawData = CVR.Data;
+ return CVR;
+}
+
+static Error skipPadding(ArrayRef<uint8_t> &Data) {
+ if (Data.empty())
+ return Error::success();
+ uint8_t Leaf = Data.front();
+ if (Leaf < LF_PAD0)
+ return Error::success();
+ // Leaf is greater than 0xf0. We should advance by the number of bytes in
+ // the low 4 bits.
+ unsigned BytesToAdvance = Leaf & 0x0F;
+ if (Data.size() < BytesToAdvance) {
+ return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
+ "Invalid padding bytes!");
+ }
+ Data = Data.drop_front(BytesToAdvance);
+ return Error::success();
+}
+
CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
: Callbacks(Callbacks) {}
@@ -45,7 +91,10 @@ Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
}
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
TYPE_RECORD(EnumVal, EnumVal, AliasName)
-#define MEMBER_RECORD(EnumName, EnumVal, Name)
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ TYPE_RECORD(EnumName, EnumVal, Name)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
+ MEMBER_RECORD(EnumName, EnumVal, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
}
@@ -63,3 +112,39 @@ Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
}
return Error::success();
}
+
+Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef<uint8_t> Data) {
+ while (!Data.empty()) {
+ const support::ulittle16_t *LeafValue;
+ if (auto EC = takeObject(Data, LeafValue))
+ return std::move(EC);
+
+ TypeLeafKind Leaf = static_cast<TypeLeafKind>(uint16_t(*LeafValue));
+ CVType Record;
+ switch (Leaf) {
+ default:
+ // Field list records do not describe their own length, so we cannot
+ // continue parsing past a type that we don't know how to deserialize.
+ return llvm::make_error<CodeViewError>(
+ cv_error_code::unknown_member_record);
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ case EnumName: { \
+ auto ExpectedRecord = deserializeMemberRecord<Name##Record>(Data, Leaf); \
+ if (!ExpectedRecord) \
+ return ExpectedRecord.takeError(); \
+ auto &Record = *ExpectedRecord; \
+ if (auto EC = Callbacks.visitTypeBegin(Record)) \
+ return EC; \
+ if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \
+ return EC; \
+ if (auto EC = Callbacks.visitTypeEnd(Record)) \
+ return EC; \
+ break; \
+ }
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
+ MEMBER_RECORD(EnumVal, EnumVal, AliasName)
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+ }
+ }
+ return Error::success();
+}
diff --git a/llvm/lib/DebugInfo/CodeView/EnumTables.cpp b/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
index d59271b2367..0e20bcb27ec 100644
--- a/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
+++ b/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
@@ -24,6 +24,12 @@ static const EnumEntry<SymbolKind> SymbolTypeNames[] = {
#undef CV_SYMBOL
};
+static const EnumEntry<TypeLeafKind> TypeLeafNames[] = {
+#define CV_TYPE(name, val) {#name, name},
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+#undef CV_TYPE
+};
+
static const EnumEntry<uint16_t> RegisterNames[] = {
CV_ENUM_CLASS_ENT(RegisterId, Unknown),
CV_ENUM_CLASS_ENT(RegisterId, VFrame),
@@ -324,6 +330,10 @@ ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames() {
return makeArrayRef(SymbolTypeNames);
}
+ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames() {
+ return makeArrayRef(TypeLeafNames);
+}
+
ArrayRef<EnumEntry<uint16_t>> getRegisterNames() {
return makeArrayRef(RegisterNames);
}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp b/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp
index 3593458565f..41aaa3c55b6 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp
@@ -11,71 +11,3 @@
using namespace llvm;
using namespace llvm::codeview;
-
-template <typename T>
-static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
- if (Data.size() < sizeof(*Res))
- return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- Res = reinterpret_cast<const T *>(Data.data());
- Data = Data.drop_front(sizeof(*Res));
- return Error::success();
-}
-
-Error TypeDeserializer::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
- FieldListRecord &Record) {
- ArrayRef<uint8_t> FieldListRecordData = CVR.Data;
- auto ExpectedRecord = FieldListRecord::deserialize(TypeRecordKind::FieldList,
- FieldListRecordData);
- if (!ExpectedRecord)
- return ExpectedRecord.takeError();
-
- Record = *ExpectedRecord;
- ArrayRef<uint8_t> MemberData = Record.getFieldListData();
-
- while (!MemberData.empty()) {
- const ulittle16_t *LeafPtr;
- if (auto EC = takeObject(MemberData, LeafPtr))
- return EC;
- TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
- switch (Leaf) {
- default:
- // Field list records do not describe their own length, so we cannot
- // continue parsing past a type that we don't know how to deserialize.
- if (auto EC = Recipient.visitUnknownMember(CVR))
- return EC;
- return llvm::make_error<CodeViewError>(
- cv_error_code::unknown_member_record);
-#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- case EnumName: { \
- TypeRecordKind RK = static_cast<TypeRecordKind>(Leaf); \
- Name##Record Member(RK); \
- if (auto EC = visitKnownMember(MemberData, Leaf, Member)) \
- return EC; \
- break; \
- }
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
- MEMBER_RECORD(EnumVal, EnumVal, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- }
- if (auto EC = skipPadding(MemberData))
- return EC;
- }
- return Error::success();
-}
-
-Error TypeDeserializer::skipPadding(ArrayRef<uint8_t> &Data) {
- if (Data.empty())
- return Error::success();
- uint8_t Leaf = Data.front();
- if (Leaf < LF_PAD0)
- return Error::success();
- // Leaf is greater than 0xf0. We should advance by the number of bytes in
- // the low 4 bits.
- unsigned BytesToAdvance = Leaf & 0x0F;
- if (Data.size() < BytesToAdvance) {
- return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
- "Invalid padding bytes!");
- }
- Data = Data.drop_front(BytesToAdvance);
- return Error::success();
-}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
index e1ec5ce9802..3f409762398 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
@@ -206,21 +206,38 @@ Error CVTypeDumper::visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {
// Reset Name to the empty string. If the visitor sets it, we know it.
Name = "";
- W->startLine() << getLeafTypeName(Record.Type) << " ("
- << HexNumber(getNextTypeIndex()) << ") {\n";
+ W->startLine() << getLeafTypeName(Record.Type);
+ if (!IsInFieldList) {
+ // If this is a field list member, don't record its type index because it
+ // doesn't have one. Only the outer field list has a type index.
+ W->getOStream() << " (" << HexNumber(getNextTypeIndex()) << ")";
+ }
+ W->getOStream() << " {\n";
W->indent();
W->printEnum("TypeLeafKind", unsigned(Record.Type),
makeArrayRef(LeafTypeNames));
+ if (Record.Type == LF_FIELDLIST) {
+ // Record that we're in a field list so that members do not get assigned
+ // type indices.
+ assert(!IsInFieldList);
+ IsInFieldList = true;
+ }
return Error::success();
}
Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
- if (Record.Type == LF_FIELDLIST)
- Name = "<field list>";
+ if (Record.Type == LF_FIELDLIST) {
+ assert(IsInFieldList);
+ IsInFieldList = false;
+ }
- // Always record some name for every type, even if Name is empty. CVUDTNames
- // is indexed by type index, and must have one entry for every type.
- recordType(Name);
+ if (!IsInFieldList) {
+ // Record every type that is not a field list member, even if Name is empty.
+ // CVUDTNames is indexed by type index, and must have one entry for every
+ // type. Field list members are not recorded, and are only referenced by
+ // their containing field list record.
+ recordType(Name);
+ }
if (PrintRecordBytes)
W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
@@ -232,6 +249,12 @@ Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
FieldListRecord &FieldList) {
+ TypeDeserializer Deserializer(*this);
+ CVTypeVisitor Visitor(Deserializer);
+ if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data))
+ return EC;
+
+ Name = "<field list>";
return Error::success();
}
@@ -550,7 +573,6 @@ Error CVTypeDumper::visitUnknownMember(const CVRecord<TypeLeafKind> &Record) {
}
Error CVTypeDumper::visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
- DictScope S(*W, "UnknownType");
W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames));
W->printNumber("Length", uint32_t(Record.Data.size()));
return Error::success();
@@ -558,7 +580,6 @@ Error CVTypeDumper::visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
NestedTypeRecord &Nested) {
- DictScope S(*W, "NestedType");
printTypeIndex("Type", Nested.getNestedType());
W->printString("Name", Nested.getName());
Name = Nested.getName();
@@ -567,7 +588,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
OneMethodRecord &Method) {
- DictScope S(*W, "OneMethod");
MethodKind K = Method.getKind();
printMemberAttributes(Method.getAccess(), K, Method.getOptions());
printTypeIndex("Type", Method.getType());
@@ -581,7 +601,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
OverloadedMethodRecord &Method) {
- DictScope S(*W, "OverloadedMethod");
W->printHex("MethodCount", Method.getNumOverloads());
printTypeIndex("MethodListIndex", Method.getMethodList());
W->printString("Name", Method.getName());
@@ -591,7 +610,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
DataMemberRecord &Field) {
- DictScope S(*W, "DataMember");
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("Type", Field.getType());
@@ -603,7 +621,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
StaticDataMemberRecord &Field) {
- DictScope S(*W, "StaticDataMember");
printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("Type", Field.getType());
@@ -614,14 +631,12 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
VFPtrRecord &VFTable) {
- DictScope S(*W, "VFPtr");
printTypeIndex("Type", VFTable.getType());
return Error::success();
}
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
EnumeratorRecord &Enum) {
- DictScope S(*W, "Enumerator");
printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
W->printNumber("EnumValue", Enum.getValue());
@@ -632,7 +647,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
BaseClassRecord &Base) {
- DictScope S(*W, "BaseClass");
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("BaseType", Base.getBaseType());
@@ -642,7 +656,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
VirtualBaseClassRecord &Base) {
- DictScope S(*W, "VirtualBaseClass");
printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
MethodOptions::None);
printTypeIndex("BaseType", Base.getBaseType());
@@ -654,7 +667,6 @@ Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
ListContinuationRecord &Cont) {
- DictScope S(*W, "ListContinuation");
printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
return Error::success();
}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
index e630be87345..47aa04fe76a 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
@@ -8,8 +8,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
using namespace llvm;
using namespace llvm::codeview;
@@ -116,7 +117,9 @@ NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
Expected<FieldListRecord>
FieldListRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
- return FieldListRecord(Data);
+ auto FieldListData = Data;
+ Data = ArrayRef<uint8_t>();
+ return FieldListRecord(FieldListData);
}
Expected<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
@@ -448,7 +451,7 @@ bool PointerRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
bool Success = true;
Success &= remapIndex(IndexMap, ReferentType);
if (isPointerToMember())
- Success &= MemberInfo.remapTypeIndices(IndexMap);
+ Success &= MemberInfo->remapTypeIndices(IndexMap);
return Success;
}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index 58c8c3fecb4..968aa06cdd2 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -84,6 +84,11 @@ private:
Error visitKnownRecordImpl(FieldListRecord &Record) {
// Don't do anything, this will get written in the call to visitTypeEnd().
+ TypeDeserializer Deserializer(*this);
+ CVTypeVisitor Visitor(Deserializer);
+
+ if (auto EC = Visitor.visitFieldListMemberStream(Record.Data))
+ return std::move(EC);
return Error::success();
}
@@ -102,6 +107,7 @@ private:
TypeTableBuilder &DestStream;
+ bool IsInFieldList{false};
size_t BeginIndexMapSize = 0;
/// Map from source type index to destination type index. Indexed by source
@@ -112,7 +118,10 @@ private:
} // end anonymous namespace
Error TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
- if (Rec.Type != TypeLeafKind::LF_FIELDLIST)
+ if (Rec.Type == TypeLeafKind::LF_FIELDLIST) {
+ assert(!IsInFieldList);
+ IsInFieldList = true;
+ } else
BeginIndexMapSize = IndexMap.size();
return Error::success();
}
@@ -121,7 +130,8 @@ Error TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
if (Rec.Type == TypeLeafKind::LF_FIELDLIST) {
IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
FieldBuilder.reset();
- } else {
+ IsInFieldList = false;
+ } else if (!IsInFieldList) {
assert(IndexMap.size() == BeginIndexMapSize + 1);
}
return Error::success();
OpenPOWER on IntegriCloud