[llvm] r270475 - [codeview] Refactor symbol records to use same pattern as types.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Mon May 23 11:49:16 PDT 2016


Author: zturner
Date: Mon May 23 13:49:06 2016
New Revision: 270475

URL: http://llvm.org/viewvc/llvm-project?rev=270475&view=rev
Log:
[codeview] Refactor symbol records to use same pattern as types.

This will pave the way to introduce a full fledged symbol visitor
similar to how we have a type visitor, thus allowing the same
dumping code to be used in llvm-readobj and llvm-pdbdump.

Differential Revision: http://reviews.llvm.org/D20384
Reviewed By: rnk

Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/tools/llvm-readobj/COFFDumper.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h?rev=270475&r1=270474&r2=270475&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h Mon May 23 13:49:06 2016
@@ -114,8 +114,8 @@ template <typename T, typename U> struct
   U Func;
 };
 
-template <typename T> struct serialize_array_tail_impl {
-  serialize_array_tail_impl(std::vector<T> &Item) : Item(Item) {}
+template <typename T> struct serialize_vector_tail_impl {
+  serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {}
 
   std::error_code deserialize(ArrayRef<uint8_t> &Data) const {
     T Field;
@@ -131,6 +131,18 @@ template <typename T> struct serialize_a
   std::vector<T> &Item;
 };
 
+template <typename T> struct serialize_arrayref_tail_impl {
+  serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {}
+
+  std::error_code deserialize(ArrayRef<uint8_t> &Data) const {
+    uint32_t Count = Data.size() / sizeof(T);
+    Item = ArrayRef<T>(reinterpret_cast<const T *>(Data.begin()), Count);
+    return std::error_code();
+  }
+
+  ArrayRef<T> &Item;
+};
+
 template <typename T> struct serialize_numeric_impl {
   serialize_numeric_impl(T &Item) : Item(Item) {}
 
@@ -147,8 +159,13 @@ serialize_array_impl<T, U> serialize_arr
 }
 
 template <typename T>
-serialize_array_tail_impl<T> serialize_array_tail(std::vector<T> &Item) {
-  return serialize_array_tail_impl<T>(Item);
+serialize_vector_tail_impl<T> serialize_array_tail(std::vector<T> &Item) {
+  return serialize_vector_tail_impl<T>(Item);
+}
+
+template <typename T>
+serialize_arrayref_tail_impl<T> serialize_array_tail(ArrayRef<T> &Item) {
+  return serialize_arrayref_tail_impl<T>(Item);
 }
 
 template <typename T> serialize_numeric_impl<T> serialize_numeric(T &Item) {
@@ -185,7 +202,13 @@ std::error_code consume(ArrayRef<uint8_t
 
 template <typename T>
 std::error_code consume(ArrayRef<uint8_t> &Data,
-                        const serialize_array_tail_impl<T> &Item) {
+                        const serialize_vector_tail_impl<T> &Item) {
+  return Item.deserialize(Data);
+}
+
+template <typename T>
+std::error_code consume(ArrayRef<uint8_t> &Data,
+                        const serialize_arrayref_tail_impl<T> &Item) {
   return Item.deserialize(Data);
 }
 

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h?rev=270475&r1=270474&r2=270475&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h Mon May 23 13:49:06 2016
@@ -10,10 +10,14 @@
 #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
 
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/DebugInfo/CodeView/RecordIterator.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
 
 namespace llvm {
 namespace codeview {
@@ -22,35 +26,300 @@ using llvm::support::ulittle16_t;
 using llvm::support::ulittle32_t;
 using llvm::support::little32_t;
 
+class SymbolRecord {
+protected:
+  explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
+
+public:
+  SymbolRecordKind getKind() const { return Kind; }
+
+private:
+  SymbolRecordKind Kind;
+};
+
 // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
 // S_LPROC32_DPC_ID
-struct ProcSym {
-  ulittle32_t PtrParent;
-  ulittle32_t PtrEnd;
-  ulittle32_t PtrNext;
-  ulittle32_t CodeSize;
-  ulittle32_t DbgStart;
-  ulittle32_t DbgEnd;
-  TypeIndex FunctionType;
-  ulittle32_t CodeOffset;
-  ulittle16_t Segment;
-  uint8_t Flags; // ProcSymFlags enum
-  // Name: The null-terminated name follows.
+class ProcSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t PtrParent;
+    ulittle32_t PtrEnd;
+    ulittle32_t PtrNext;
+    ulittle32_t CodeSize;
+    ulittle32_t DbgStart;
+    ulittle32_t DbgEnd;
+    TypeIndex FunctionType;
+    ulittle32_t CodeOffset;
+    ulittle16_t Segment;
+    uint8_t Flags; // ProcSymFlags enum
+                   // Name: The null-terminated name follows.
+  };
+
+  ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
+          StringRef Name)
+      : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
+  }
+
+  static ErrorOr<ProcSym> deserialize(SymbolRecordKind Kind,
+                                      uint32_t RecordOffset,
+                                      ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return ProcSym(Kind, RecordOffset, H, Name);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, CodeOffset);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
+};
+
+struct BinaryAnnotationIterator {
+  struct AnnotationData {
+    BinaryAnnotationsOpCode OpCode;
+    StringRef Name;
+    uint32_t U1;
+    uint32_t U2;
+    int32_t S1;
+  };
+
+  BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
+  BinaryAnnotationIterator() {}
+  BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
+      : Data(Other.Data) {}
+
+  bool operator==(BinaryAnnotationIterator Other) const {
+    return Data == Other.Data;
+  }
+
+  bool operator!=(BinaryAnnotationIterator Other) const {
+    return !(*this == Other);
+  }
+
+  BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
+    Data = Other.Data;
+    return *this;
+  }
+
+  BinaryAnnotationIterator &operator++() {
+    if (!ParseCurrentAnnotation()) {
+      *this = BinaryAnnotationIterator();
+      return *this;
+    }
+    Data = Next;
+    Next = ArrayRef<uint8_t>();
+    Current.reset();
+    return *this;
+  }
+
+  BinaryAnnotationIterator operator++(int) {
+    BinaryAnnotationIterator Orig(*this);
+    ++(*this);
+    return Orig;
+  }
+
+  const AnnotationData &operator*() {
+    ParseCurrentAnnotation();
+    return Current.getValue();
+  }
+
+private:
+  static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
+    if (Annotations.empty())
+      return -1;
+
+    uint8_t FirstByte = Annotations.front();
+    Annotations = Annotations.drop_front();
+
+    if ((FirstByte & 0x80) == 0x00)
+      return FirstByte;
+
+    if (Annotations.empty())
+      return -1;
+
+    uint8_t SecondByte = Annotations.front();
+    Annotations = Annotations.drop_front();
+
+    if ((FirstByte & 0xC0) == 0x80)
+      return ((FirstByte & 0x3F) << 8) | SecondByte;
+
+    if (Annotations.empty())
+      return -1;
+
+    uint8_t ThirdByte = Annotations.front();
+    Annotations = Annotations.drop_front();
+
+    if (Annotations.empty())
+      return -1;
+
+    uint8_t FourthByte = Annotations.front();
+    Annotations = Annotations.drop_front();
+
+    if ((FirstByte & 0xE0) == 0xC0)
+      return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
+             (ThirdByte << 8) | FourthByte;
+
+    return -1;
+  };
+
+  static int32_t DecodeSignedOperand(uint32_t Operand) {
+    if (Operand & 1)
+      return -(Operand >> 1);
+    return Operand >> 1;
+  };
+
+  static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
+    return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
+  };
+
+  bool ParseCurrentAnnotation() {
+    if (Current.hasValue())
+      return true;
+
+    Next = Data;
+    uint32_t Op = GetCompressedAnnotation(Next);
+    AnnotationData Result;
+    Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
+    switch (Result.OpCode) {
+    case BinaryAnnotationsOpCode::Invalid:
+      Result.Name = "Invalid";
+      Next = ArrayRef<uint8_t>();
+      break;
+    case BinaryAnnotationsOpCode::CodeOffset:
+      Result.Name = "CodeOffset";
+      Result.U1 = GetCompressedAnnotation(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
+      Result.Name = "ChangeCodeOffsetBase";
+      Result.U1 = GetCompressedAnnotation(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeOffset:
+      Result.Name = "ChangeCodeOffset";
+      Result.U1 = GetCompressedAnnotation(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeLength:
+      Result.Name = "ChangeCodeLength";
+      Result.U1 = GetCompressedAnnotation(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeFile:
+      Result.Name = "ChangeFile";
+      Result.U1 = GetCompressedAnnotation(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeLineEndDelta:
+      Result.Name = "ChangeLineEndDelta";
+      Result.U1 = GetCompressedAnnotation(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeRangeKind:
+      Result.Name = "ChangeRangeKind";
+      Result.U1 = GetCompressedAnnotation(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeColumnStart:
+      Result.Name = "ChangeColumnStart";
+      Result.U1 = GetCompressedAnnotation(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeColumnEnd:
+      Result.Name = "ChangeColumnEnd";
+      Result.U1 = GetCompressedAnnotation(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeLineOffset:
+      Result.Name = "ChangeLineOffset";
+      Result.S1 = DecodeSignedOperand(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
+      Result.Name = "ChangeColumnEndDelta";
+      Result.S1 = DecodeSignedOperand(Next);
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
+      Result.Name = "ChangeCodeOffsetAndLineOffset";
+      uint32_t Annotation = GetCompressedAnnotation(Next);
+      Result.S1 = DecodeSignedOperand(Annotation >> 4);
+      Result.U1 = Annotation & 0xf;
+      break;
+    }
+    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
+      Result.Name = "ChangeCodeLengthAndCodeOffset";
+      Result.U1 = GetCompressedAnnotation(Next);
+      Result.U2 = GetCompressedAnnotation(Next);
+      break;
+    }
+    }
+    Current = Result;
+    return true;
+  }
+
+  Optional<AnnotationData> Current;
+  ArrayRef<uint8_t> Data;
+  ArrayRef<uint8_t> Next;
 };
 
 // S_INLINESITE
-struct InlineSiteSym {
-  ulittle32_t PtrParent;
-  ulittle32_t PtrEnd;
-  TypeIndex Inlinee;
-  // BinaryAnnotations
+class InlineSiteSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t PtrParent;
+    ulittle32_t PtrEnd;
+    TypeIndex Inlinee;
+    // BinaryAnnotations
+  };
+
+  InlineSiteSym(uint32_t RecordOffset, const Hdr *H,
+                ArrayRef<uint8_t> Annotations)
+      : SymbolRecord(SymbolRecordKind::InlineSiteSym),
+        RecordOffset(RecordOffset), Header(*H), Annotations(Annotations) {}
+
+  static ErrorOr<InlineSiteSym> deserialize(SymbolRecordKind Kind,
+                                            uint32_t RecordOffset,
+                                            ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    ArrayRef<uint8_t> Annotations;
+    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Annotations));
+
+    return InlineSiteSym(RecordOffset, H, Annotations);
+  }
+
+  llvm::iterator_range<BinaryAnnotationIterator> annotations() const {
+    return llvm::make_range(BinaryAnnotationIterator(Annotations),
+                            BinaryAnnotationIterator());
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+
+private:
+  ArrayRef<uint8_t> Annotations;
 };
 
 // S_LOCAL
-struct LocalSym {
-  TypeIndex Type;
-  ulittle16_t Flags; // LocalSymFlags enum
-  // Name: The null-terminated name follows.
+class LocalSym : public SymbolRecord {
+public:
+  struct Hdr {
+    TypeIndex Type;
+    ulittle16_t Flags; // LocalSymFlags enum
+                       // Name: The null-terminated name follows.
+  };
+
+  LocalSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+      : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset),
+        Header(*H), Name(Name) {}
+
+  static ErrorOr<LocalSym> deserialize(SymbolRecordKind Kind,
+                                       uint32_t RecordOffset,
+                                       ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return LocalSym(RecordOffset, H, Name);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
 };
 
 struct LocalVariableAddrRange {
@@ -67,182 +336,728 @@ struct LocalVariableAddrGap {
 enum : uint16_t { MaxDefRange = 0xf000 };
 
 // S_DEFRANGE
-struct DefRangeSym {
-  ulittle32_t Program;
-  LocalVariableAddrRange Range;
-  // LocalVariableAddrGap Gaps[];
+class DefRangeSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t Program;
+    LocalVariableAddrRange Range;
+    // LocalVariableAddrGap Gaps[];
+  };
+
+  DefRangeSym(uint32_t RecordOffset, const Hdr *H,
+              ArrayRef<LocalVariableAddrGap> Gaps)
+      : SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset),
+        Header(*H), Gaps(Gaps) {}
+
+  static ErrorOr<DefRangeSym> deserialize(SymbolRecordKind Kind,
+                                          uint32_t RecordOffset,
+                                          ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    ArrayRef<LocalVariableAddrGap> Gaps;
+    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+    return DefRangeSym(RecordOffset, H, Gaps);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, Range);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  ArrayRef<LocalVariableAddrGap> Gaps;
 };
 
 // S_DEFRANGE_SUBFIELD
-struct DefRangeSubfieldSym {
-  ulittle32_t Program;
-  ulittle16_t OffsetInParent;
-  LocalVariableAddrRange Range;
-  // LocalVariableAddrGap Gaps[];
+class DefRangeSubfieldSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t Program;
+    ulittle16_t OffsetInParent;
+    LocalVariableAddrRange Range;
+    // LocalVariableAddrGap Gaps[];
+  };
+  DefRangeSubfieldSym(uint32_t RecordOffset, const Hdr *H,
+                      ArrayRef<LocalVariableAddrGap> Gaps)
+      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
+        RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+  static ErrorOr<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind,
+                                                  uint32_t RecordOffset,
+                                                  ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    ArrayRef<LocalVariableAddrGap> Gaps;
+    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+    return DefRangeSubfieldSym(RecordOffset, H, Gaps);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, Range);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  ArrayRef<LocalVariableAddrGap> Gaps;
 };
 
 // S_DEFRANGE_REGISTER
-struct DefRangeRegisterSym {
-  ulittle16_t Register;
-  ulittle16_t MayHaveNoName;
-  LocalVariableAddrRange Range;
-  // LocalVariableAddrGap Gaps[];
+class DefRangeRegisterSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle16_t Register;
+    ulittle16_t MayHaveNoName;
+    LocalVariableAddrRange Range;
+    // LocalVariableAddrGap Gaps[];
+  };
+
+  DefRangeRegisterSym(uint32_t RecordOffset, const Hdr *H,
+                      ArrayRef<LocalVariableAddrGap> Gaps)
+      : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
+        RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+  DefRangeRegisterSym(uint16_t Register, uint16_t MayHaveNoName,
+                      uint32_t OffsetStart, uint16_t ISectStart, uint16_t Range,
+                      ArrayRef<LocalVariableAddrGap> Gaps)
+      : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), RecordOffset(0),
+        Gaps(Gaps) {
+    Header.Register = Register;
+    Header.MayHaveNoName = MayHaveNoName;
+    Header.Range.OffsetStart = OffsetStart;
+    Header.Range.ISectStart = ISectStart;
+    Header.Range.Range = Range;
+  }
+
+  static ErrorOr<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind,
+                                                  uint32_t RecordOffset,
+                                                  ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    ArrayRef<LocalVariableAddrGap> Gaps;
+    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+    return DefRangeRegisterSym(RecordOffset, H, Gaps);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, Range);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  ArrayRef<LocalVariableAddrGap> Gaps;
 };
 
 // S_DEFRANGE_SUBFIELD_REGISTER
-struct DefRangeSubfieldRegisterSym {
-  ulittle16_t Register; // Register to which the variable is relative
-  ulittle16_t MayHaveNoName;
-  ulittle32_t OffsetInParent;
-  LocalVariableAddrRange Range;
-  // LocalVariableAddrGap Gaps[];
+class DefRangeSubfieldRegisterSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle16_t Register; // Register to which the variable is relative
+    ulittle16_t MayHaveNoName;
+    ulittle32_t OffsetInParent;
+    LocalVariableAddrRange Range;
+    // LocalVariableAddrGap Gaps[];
+  };
+
+  DefRangeSubfieldRegisterSym(uint32_t RecordOffset, const Hdr *H,
+                              ArrayRef<LocalVariableAddrGap> Gaps)
+      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
+        RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+  DefRangeSubfieldRegisterSym(uint16_t Register, uint16_t MayHaveNoName,
+                              uint32_t OffsetInParent,
+                              ArrayRef<LocalVariableAddrGap> Gaps)
+      : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
+        RecordOffset(0), Gaps(Gaps) {
+    Header.Register = Register;
+    Header.MayHaveNoName = MayHaveNoName;
+    Header.OffsetInParent = OffsetInParent;
+  }
+
+  static ErrorOr<DefRangeSubfieldRegisterSym>
+  deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+              ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    ArrayRef<LocalVariableAddrGap> Gaps;
+    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+    return DefRangeSubfieldRegisterSym(RecordOffset, H, Gaps);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, Range);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  ArrayRef<LocalVariableAddrGap> Gaps;
 };
 
 // S_DEFRANGE_FRAMEPOINTER_REL
-struct DefRangeFramePointerRelSym {
-  little32_t Offset; // Offset from the frame pointer register
-  LocalVariableAddrRange Range;
-  // LocalVariableAddrGap Gaps[];
+class DefRangeFramePointerRelSym : public SymbolRecord {
+public:
+  struct Hdr {
+    little32_t Offset; // Offset from the frame pointer register
+    LocalVariableAddrRange Range;
+    // LocalVariableAddrGap Gaps[];
+  };
+
+  DefRangeFramePointerRelSym(uint32_t RecordOffset, const Hdr *H,
+                             ArrayRef<LocalVariableAddrGap> Gaps)
+      : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
+        RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+  static ErrorOr<DefRangeFramePointerRelSym>
+  deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+              ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    ArrayRef<LocalVariableAddrGap> Gaps;
+    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+    return DefRangeFramePointerRelSym(RecordOffset, H, Gaps);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, Range);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  ArrayRef<LocalVariableAddrGap> Gaps;
 };
 
-// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
-struct DefRangeFramePointerRelFullScopeSym {
-  little32_t Offset; // Offset from the frame pointer register
+// S_DEFRANGE_REGISTER_REL
+class DefRangeRegisterRelSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle16_t BaseRegister;
+    ulittle16_t Flags;
+    little32_t BasePointerOffset;
+    LocalVariableAddrRange Range;
+    // LocalVariableAddrGap Gaps[];
+  };
+
+  DefRangeRegisterRelSym(uint32_t RecordOffset, const Hdr *H,
+                         ArrayRef<LocalVariableAddrGap> Gaps)
+      : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
+        RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
+
+  DefRangeRegisterRelSym(uint16_t BaseRegister, uint16_t Flags,
+                         int32_t BasePointerOffset, uint32_t OffsetStart,
+                         uint16_t ISectStart, uint16_t Range,
+                         ArrayRef<LocalVariableAddrGap> Gaps)
+      : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), RecordOffset(0),
+        Gaps(Gaps) {
+    Header.BaseRegister = BaseRegister;
+    Header.Flags = Flags;
+    Header.BasePointerOffset = BasePointerOffset;
+    Header.Range.OffsetStart = OffsetStart;
+    Header.Range.ISectStart = ISectStart;
+    Header.Range.Range = Range;
+  }
+
+  static ErrorOr<DefRangeRegisterRelSym> deserialize(SymbolRecordKind Kind,
+                                                     uint32_t RecordOffset,
+                                                     ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    ArrayRef<LocalVariableAddrGap> Gaps;
+    CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
+
+    return DefRangeRegisterRelSym(RecordOffset, H, Gaps);
+  }
+
+  bool hasSpilledUDTMember() const { return Header.Flags & 1; }
+  uint16_t offsetInParent() const { return Header.Flags >> 4; }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, Range);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  ArrayRef<LocalVariableAddrGap> Gaps;
 };
 
-// S_DEFRANGE_REGISTER_REL
-struct DefRangeRegisterRelSym {
-  ulittle16_t BaseRegister;
-  ulittle16_t Flags;
-  little32_t BasePointerOffset;
-  LocalVariableAddrRange Range;
-  // LocalVariableAddrGap Gaps[];
+// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
+class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
+public:
+  struct Hdr {
+    little32_t Offset; // Offset from the frame pointer register
+  };
+
+  DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset, const Hdr *H)
+      : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
+        RecordOffset(RecordOffset), Header(*H) {}
+
+  static ErrorOr<DefRangeFramePointerRelFullScopeSym>
+  deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
+              ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    CV_DESERIALIZE(Data, H);
+
+    return DefRangeFramePointerRelFullScopeSym(RecordOffset, H);
+  }
 
-  bool hasSpilledUDTMember() const { return Flags & 1; }
-  uint16_t offsetInParent() const { return Flags >> 4; }
+  uint32_t RecordOffset;
+  Hdr Header;
 };
 
 // S_BLOCK32
-struct BlockSym {
-  ulittle32_t PtrParent;
-  ulittle32_t PtrEnd;
-  ulittle32_t CodeSize;
-  ulittle32_t CodeOffset;
-  ulittle16_t Segment;
-  // Name: The null-terminated name follows.
+class BlockSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t PtrParent;
+    ulittle32_t PtrEnd;
+    ulittle32_t CodeSize;
+    ulittle32_t CodeOffset;
+    ulittle16_t Segment;
+    // Name: The null-terminated name follows.
+  };
+
+  BlockSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+      : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset),
+        Header(*H), Name(Name) {}
+
+  static ErrorOr<BlockSym> deserialize(SymbolRecordKind Kind,
+                                       uint32_t RecordOffset,
+                                       ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return BlockSym(RecordOffset, H, Name);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, CodeOffset);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
 };
 
 // S_LABEL32
-struct LabelSym {
-  ulittle32_t CodeOffset;
-  ulittle16_t Segment;
-  uint8_t Flags; // CV_PROCFLAGS
-  // Name: The null-terminated name follows.
+class LabelSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t CodeOffset;
+    ulittle16_t Segment;
+    uint8_t Flags; // CV_PROCFLAGS
+                   // Name: The null-terminated name follows.
+  };
+
+  LabelSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+      : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset),
+        Header(*H), Name(Name) {}
+
+  static ErrorOr<LabelSym> deserialize(SymbolRecordKind Kind,
+                                       uint32_t RecordOffset,
+                                       ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return LabelSym(RecordOffset, H, Name);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, CodeOffset);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
 };
 
 // S_OBJNAME
-struct ObjNameSym {
-  ulittle32_t Signature;
-  // Name: The null-terminated name follows.
+class ObjNameSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t Signature;
+    // Name: The null-terminated name follows.
+  };
+
+  ObjNameSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+      : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset),
+        Header(*H), Name(Name) {}
+
+  static ErrorOr<ObjNameSym> deserialize(SymbolRecordKind Kind,
+                                         uint32_t RecordOffset,
+                                         ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return ObjNameSym(RecordOffset, H, Name);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
 };
 
 // S_COMPILE3
-struct CompileSym3 {
-  ulittle32_t flags; // CompileSym3Flags enum
-  uint8_t getLanguage() const { return flags & 0xff; }
-  ulittle16_t Machine; // CPUType
-  ulittle16_t VersionFrontendMajor;
-  ulittle16_t VersionFrontendMinor;
-  ulittle16_t VersionFrontendBuild;
-  ulittle16_t VersionFrontendQFE;
-  ulittle16_t VersionBackendMajor;
-  ulittle16_t VersionBackendMinor;
-  ulittle16_t VersionBackendBuild;
-  ulittle16_t VersionBackendQFE;
-  // VersionString: The null-terminated version string follows.
+class CompileSym3 : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t flags; // CompileSym3Flags enum
+    uint8_t getLanguage() const { return flags & 0xff; }
+    ulittle16_t Machine; // CPUType
+    ulittle16_t VersionFrontendMajor;
+    ulittle16_t VersionFrontendMinor;
+    ulittle16_t VersionFrontendBuild;
+    ulittle16_t VersionFrontendQFE;
+    ulittle16_t VersionBackendMajor;
+    ulittle16_t VersionBackendMinor;
+    ulittle16_t VersionBackendBuild;
+    ulittle16_t VersionBackendQFE;
+    // VersionString: The null-terminated version string follows.
+  };
+
+  CompileSym3(uint32_t RecordOffset, const Hdr *H, StringRef Version)
+      : SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset),
+        Header(*H), Version(Version) {}
+
+  static ErrorOr<CompileSym3> deserialize(SymbolRecordKind Kind,
+                                          uint32_t RecordOffset,
+                                          ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Version;
+    CV_DESERIALIZE(Data, H, Version);
+
+    return CompileSym3(RecordOffset, H, Version);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Version;
 };
 
 // S_FRAMEPROC
-struct FrameProcSym {
-  ulittle32_t TotalFrameBytes;
-  ulittle32_t PaddingFrameBytes;
-  ulittle32_t OffsetToPadding;
-  ulittle32_t BytesOfCalleeSavedRegisters;
-  ulittle32_t OffsetOfExceptionHandler;
-  ulittle16_t SectionIdOfExceptionHandler;
-  ulittle32_t Flags;
+class FrameProcSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t TotalFrameBytes;
+    ulittle32_t PaddingFrameBytes;
+    ulittle32_t OffsetToPadding;
+    ulittle32_t BytesOfCalleeSavedRegisters;
+    ulittle32_t OffsetOfExceptionHandler;
+    ulittle16_t SectionIdOfExceptionHandler;
+    ulittle32_t Flags;
+  };
+
+  FrameProcSym(uint32_t RecordOffset, const Hdr *H)
+      : SymbolRecord(SymbolRecordKind::FrameProcSym),
+        RecordOffset(RecordOffset), Header(*H) {}
+
+  static ErrorOr<FrameProcSym> deserialize(SymbolRecordKind Kind,
+                                           uint32_t RecordOffset,
+                                           ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    CV_DESERIALIZE(Data, H);
+
+    return FrameProcSym(RecordOffset, H);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
 };
 
 // S_CALLSITEINFO
-struct CallSiteInfoSym {
-  ulittle32_t CodeOffset;
-  ulittle16_t Segment;
-  ulittle16_t Reserved;
-  TypeIndex Type;
+class CallSiteInfoSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t CodeOffset;
+    ulittle16_t Segment;
+    ulittle16_t Reserved;
+    TypeIndex Type;
+  };
+
+  CallSiteInfoSym(uint32_t RecordOffset, const Hdr *H)
+      : SymbolRecord(SymbolRecordKind::CallSiteInfoSym),
+        RecordOffset(RecordOffset), Header(*H) {}
+
+  static ErrorOr<CallSiteInfoSym> deserialize(SymbolRecordKind Kind,
+                                              uint32_t RecordOffset,
+                                              ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    CV_DESERIALIZE(Data, H);
+
+    return CallSiteInfoSym(RecordOffset, H);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, CodeOffset);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
 };
 
 // S_HEAPALLOCSITE
-struct HeapAllocationSiteSym {
-  ulittle32_t CodeOffset;
-  ulittle16_t Segment;
-  ulittle16_t CallInstructionSize;
-  TypeIndex Type;
+class HeapAllocationSiteSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t CodeOffset;
+    ulittle16_t Segment;
+    ulittle16_t CallInstructionSize;
+    TypeIndex Type;
+  };
+
+  HeapAllocationSiteSym(uint32_t RecordOffset, const Hdr *H)
+      : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
+        RecordOffset(RecordOffset), Header(*H) {}
+
+  static ErrorOr<HeapAllocationSiteSym> deserialize(SymbolRecordKind Kind,
+                                                    uint32_t RecordOffset,
+                                                    ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    CV_DESERIALIZE(Data, H);
+
+    return HeapAllocationSiteSym(RecordOffset, H);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, CodeOffset);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
 };
 
 // S_FRAMECOOKIE
-struct FrameCookieSym {
-  ulittle32_t CodeOffset;
-  ulittle16_t Register;
-  ulittle32_t CookieKind;
+class FrameCookieSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t CodeOffset;
+    ulittle16_t Register;
+    ulittle32_t CookieKind;
+  };
+
+  FrameCookieSym(uint32_t RecordOffset, const Hdr *H)
+      : SymbolRecord(SymbolRecordKind::FrameCookieSym),
+        RecordOffset(RecordOffset), Header(*H) {}
+
+  static ErrorOr<FrameCookieSym> deserialize(SymbolRecordKind Kind,
+                                             uint32_t RecordOffset,
+                                             ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    CV_DESERIALIZE(Data, H);
+
+    return FrameCookieSym(RecordOffset, H);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, CodeOffset);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
 };
 
 // S_UDT, S_COBOLUDT
-struct UDTSym {
-  TypeIndex Type; // Type of the UDT
-  // Name: The null-terminated name follows.
+class UDTSym : public SymbolRecord {
+public:
+  struct Hdr {
+    TypeIndex Type; // Type of the UDT
+                    // Name: The null-terminated name follows.
+  };
+
+  UDTSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+      : SymbolRecord(SymbolRecordKind::UDTSym), RecordOffset(RecordOffset),
+        Header(*H), Name(Name) {}
+
+  static ErrorOr<UDTSym> deserialize(SymbolRecordKind Kind,
+                                     uint32_t RecordOffset,
+                                     ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return UDTSym(RecordOffset, H, Name);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
 };
 
 // S_BUILDINFO
-struct BuildInfoSym {
-  ulittle32_t BuildId;
+class BuildInfoSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t BuildId;
+  };
+
+  BuildInfoSym(uint32_t RecordOffset, const Hdr *H)
+      : SymbolRecord(SymbolRecordKind::BuildInfoSym),
+        RecordOffset(RecordOffset), Header(*H) {}
+
+  static ErrorOr<BuildInfoSym> deserialize(SymbolRecordKind Kind,
+                                           uint32_t RecordOffset,
+                                           ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    CV_DESERIALIZE(Data, H);
+
+    return BuildInfoSym(RecordOffset, H);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
 };
 
 // S_BPREL32
-struct BPRelativeSym {
-  little32_t Offset;  // Offset from the base pointer register
-  TypeIndex Type;     // Type of the variable
-  // Name: The null-terminated name follows.
+class BPRelativeSym : public SymbolRecord {
+public:
+  struct Hdr {
+    little32_t Offset; // Offset from the base pointer register
+    TypeIndex Type;    // Type of the variable
+                       // Name: The null-terminated name follows.
+  };
+
+  BPRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+      : SymbolRecord(SymbolRecordKind::BPRelativeSym),
+        RecordOffset(RecordOffset), Header(*H), Name(Name) {}
+
+  static ErrorOr<BPRelativeSym> deserialize(SymbolRecordKind Kind,
+                                            uint32_t RecordOffset,
+                                            ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return BPRelativeSym(RecordOffset, H, Name);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
 };
 
 // S_REGREL32
-struct RegRelativeSym {
-  ulittle32_t Offset;   // Offset from the register
-  TypeIndex Type;       // Type of the variable
-  ulittle16_t Register; // Register to which the variable is relative
-  // Name: The null-terminated name follows.
+class RegRelativeSym : public SymbolRecord {
+public:
+  struct Hdr {
+    ulittle32_t Offset;   // Offset from the register
+    TypeIndex Type;       // Type of the variable
+    ulittle16_t Register; // Register to which the variable is relative
+                          // Name: The null-terminated name follows.
+  };
+
+  RegRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+      : SymbolRecord(SymbolRecordKind::RegRelativeSym),
+        RecordOffset(RecordOffset), Header(*H), Name(Name) {}
+
+  static ErrorOr<RegRelativeSym> deserialize(SymbolRecordKind Kind,
+                                             uint32_t RecordOffset,
+                                             ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return RegRelativeSym(RecordOffset, H, Name);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
 };
 
 // S_CONSTANT, S_MANCONSTANT
-struct ConstantSym {
-  TypeIndex Type;
-  // Value: The value of the constant.
-  // Name: The null-terminated name follows.
+class ConstantSym : public SymbolRecord {
+public:
+  struct Hdr {
+    TypeIndex Type;
+    // Value: The value of the constant.
+    // Name: The null-terminated name follows.
+  };
+
+  ConstantSym(uint32_t RecordOffset, const Hdr *H, const APSInt &Value,
+              StringRef Name)
+      : SymbolRecord(SymbolRecordKind::ConstantSym), RecordOffset(RecordOffset),
+        Header(*H), Value(Value), Name(Name) {}
+
+  static ErrorOr<ConstantSym> deserialize(SymbolRecordKind Kind,
+                                          uint32_t RecordOffset,
+                                          ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    APSInt Value;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Value, Name);
+
+    return ConstantSym(RecordOffset, H, Value, Name);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  APSInt Value;
+  StringRef Name;
 };
 
 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
-struct DataSym {
-  TypeIndex Type;
-  ulittle32_t DataOffset;
-  ulittle16_t Segment;
-  // Name: The null-terminated name follows.
+class DataSym : public SymbolRecord {
+public:
+  struct Hdr {
+    TypeIndex Type;
+    ulittle32_t DataOffset;
+    ulittle16_t Segment;
+    // Name: The null-terminated name follows.
+  };
+
+  DataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+      : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset),
+        Header(*H), Name(Name) {}
+
+  static ErrorOr<DataSym> deserialize(SymbolRecordKind Kind,
+                                      uint32_t RecordOffset,
+                                      ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return DataSym(RecordOffset, H, Name);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, DataOffset);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
 };
 
 // S_LTHREAD32, S_GTHREAD32
-struct ThreadLocalDataSym {
-  TypeIndex Type;
-  ulittle32_t DataOffset;
-  ulittle16_t Segment;
-  // Name: The null-terminated name follows.
+class ThreadLocalDataSym : public SymbolRecord {
+public:
+  struct Hdr {
+    TypeIndex Type;
+    ulittle32_t DataOffset;
+    ulittle16_t Segment;
+    // Name: The null-terminated name follows.
+  };
+
+  ThreadLocalDataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
+      : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
+        RecordOffset(RecordOffset), Header(*H), Name(Name) {}
+
+  static ErrorOr<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind,
+                                                 uint32_t RecordOffset,
+                                                 ArrayRef<uint8_t> &Data) {
+    const Hdr *H = nullptr;
+    StringRef Name;
+    CV_DESERIALIZE(Data, H, Name);
+
+    return ThreadLocalDataSym(RecordOffset, H, Name);
+  }
+
+  uint32_t getRelocationOffset() const {
+    return RecordOffset + offsetof(Hdr, DataOffset);
+  }
+
+  uint32_t RecordOffset;
+  Hdr Header;
+  StringRef Name;
 };
 
 typedef RecordIterator<SymbolRecordKind> SymbolIterator;

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=270475&r1=270474&r2=270475&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Mon May 23 13:49:06 2016
@@ -734,25 +734,25 @@ void CodeViewDebug::emitLocalVariable(co
       continue;
 
     if (DefRange.InMemory) {
-      DefRangeRegisterRelSym Sym{};
+      DefRangeRegisterRelSym Sym(DefRange.CVRegister, 0, DefRange.DataOffset, 0,
+                                 0, 0, ArrayRef<LocalVariableAddrGap>());
       ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL);
-      Sym.BaseRegister = DefRange.CVRegister;
-      Sym.Flags = 0; // Unclear what matters here.
-      Sym.BasePointerOffset = DefRange.DataOffset;
       BytePrefix +=
           StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind));
-      BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym),
-                              sizeof(Sym) - sizeof(LocalVariableAddrRange));
+      BytePrefix +=
+          StringRef(reinterpret_cast<const char *>(&Sym.Header),
+                    sizeof(Sym.Header) - sizeof(LocalVariableAddrRange));
     } else {
       assert(DefRange.DataOffset == 0 && "unexpected offset into register");
-      DefRangeRegisterSym Sym{};
+      // Unclear what matters here.
+      DefRangeRegisterSym Sym(DefRange.CVRegister, 0, 0, 0, 0,
+                              ArrayRef<LocalVariableAddrGap>());
       ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER);
-      Sym.Register = DefRange.CVRegister;
-      Sym.MayHaveNoName = 0; // Unclear what matters here.
       BytePrefix +=
           StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind));
-      BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym),
-                              sizeof(Sym) - sizeof(LocalVariableAddrRange));
+      BytePrefix +=
+          StringRef(reinterpret_cast<const char *>(&Sym.Header),
+                    sizeof(Sym.Header) - sizeof(LocalVariableAddrRange));
     }
     OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix);
   }

Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=270475&r1=270474&r2=270475&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Mon May 23 13:49:06 2016
@@ -98,8 +98,8 @@ private:
   }
   void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
                                    const coff_section *Sec,
-                                   StringRef SectionContents);
-  void printLocalVariableAddrGap(StringRef &SymData);
+                                   uint32_t RelocationOffset);
+  void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
 
   void printCodeViewSymbolsSubsection(StringRef Subsection,
                                       const SectionRef &Section,
@@ -110,6 +110,10 @@ private:
   void printCodeViewInlineeLines(StringRef Subsection);
 
   void printRelocatedField(StringRef Label, const coff_section *Sec,
+                           uint32_t RelocOffset, uint32_t Offset,
+                           StringRef *RelocSym = nullptr);
+
+  void printRelocatedField(StringRef Label, const coff_section *Sec,
                            StringRef SectionContents, const ulittle32_t *Field,
                            StringRef *RelocSym = nullptr);
 
@@ -208,6 +212,17 @@ std::error_code COFFDumper::resolveSymbo
 }
 
 void COFFDumper::printRelocatedField(StringRef Label, const coff_section *Sec,
+                                     uint32_t RelocOffset, uint32_t Offset,
+                                     StringRef *RelocSym) {
+  StringRef SymStorage;
+  StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
+  if (!resolveSymbolName(Sec, RelocOffset, Symbol))
+    W.printSymbolOffset(Label, Symbol, Offset);
+  else
+    W.printHex(Label, RelocOffset);
+}
+
+void COFFDumper::printRelocatedField(StringRef Label, const coff_section *Sec,
                                      StringRef SectionContents,
                                      const ulittle32_t *Field,
                                      StringRef *RelocSym) {
@@ -1011,6 +1026,7 @@ void COFFDumper::printCodeViewSymbolsSub
     StringRef OrigSymData = SymData;
 
     Data = Data.drop_front(Rec->RecordLen - 2);
+    uint32_t RecordOffset = SymData.data() - SectionContents.data();
 
     SymbolKind Kind = static_cast<SymbolKind>(uint16_t(Rec->RecordKind));
     switch (Kind) {
@@ -1021,26 +1037,31 @@ void COFFDumper::printCodeViewSymbolsSub
     case S_LPROC32_DPC:
     case S_LPROC32_DPC_ID: {
       DictScope S(W, "ProcStart");
-      const ProcSym *Proc;
-      error(consumeObject(SymData, Proc));
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto ProcOrError = ProcSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!ProcOrError)
+        error(ProcOrError.getError());
+      auto &Proc = ProcOrError.get();
+
       if (InFunctionScope)
         return error(object_error::parse_failed);
       InFunctionScope = true;
 
       StringRef LinkageName;
-      StringRef DisplayName = SymData.split('\0').first;
-      W.printHex("PtrParent", Proc->PtrParent);
-      W.printHex("PtrEnd", Proc->PtrEnd);
-      W.printHex("PtrNext", Proc->PtrNext);
-      W.printHex("CodeSize", Proc->CodeSize);
-      W.printHex("DbgStart", Proc->DbgStart);
-      W.printHex("DbgEnd", Proc->DbgEnd);
-      printTypeIndex("FunctionType", Proc->FunctionType);
-      printRelocatedField("CodeOffset", Sec, SectionContents, &Proc->CodeOffset,
-                          &LinkageName);
-      W.printHex("Segment", Proc->Segment);
-      W.printFlags("Flags", Proc->Flags, makeArrayRef(ProcSymFlagNames));
-      W.printString("DisplayName", DisplayName);
+      W.printHex("PtrParent", Proc.Header.PtrParent);
+      W.printHex("PtrEnd", Proc.Header.PtrEnd);
+      W.printHex("PtrNext", Proc.Header.PtrNext);
+      W.printHex("CodeSize", Proc.Header.CodeSize);
+      W.printHex("DbgStart", Proc.Header.DbgStart);
+      W.printHex("DbgEnd", Proc.Header.DbgEnd);
+      printTypeIndex("FunctionType", Proc.Header.FunctionType);
+      printRelocatedField("CodeOffset", Sec, Proc.getRelocationOffset(),
+                          Proc.Header.CodeOffset, &LinkageName);
+      W.printHex("Segment", Proc.Header.Segment);
+      W.printFlags("Flags", static_cast<uint8_t>(Proc.Header.Flags),
+                   makeArrayRef(ProcSymFlagNames));
+      W.printString("DisplayName", Proc.Name);
       W.printString("LinkageName", LinkageName);
       break;
     }
@@ -1053,18 +1074,21 @@ void COFFDumper::printCodeViewSymbolsSub
 
     case S_BLOCK32: {
       DictScope S(W, "BlockStart");
-      const BlockSym *Block;
-      error(consumeObject(SymData, Block));
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto BlockOrError = BlockSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!BlockOrError)
+        error(BlockOrError.getError());
+      auto &Block = BlockOrError.get();
 
-      StringRef BlockName = SymData.split('\0').first;
       StringRef LinkageName;
-      W.printHex("PtrParent", Block->PtrParent);
-      W.printHex("PtrEnd", Block->PtrEnd);
-      W.printHex("CodeSize", Block->CodeSize);
-      printRelocatedField("CodeOffset", Sec, SectionContents,
-                          &Block->CodeOffset, &LinkageName);
-      W.printHex("Segment", Block->Segment);
-      W.printString("BlockName", BlockName);
+      W.printHex("PtrParent", Block.Header.PtrParent);
+      W.printHex("PtrEnd", Block.Header.PtrEnd);
+      W.printHex("CodeSize", Block.Header.CodeSize);
+      printRelocatedField("CodeOffset", Sec, Block.getRelocationOffset(),
+                          Block.Header.CodeOffset, &LinkageName);
+      W.printHex("Segment", Block.Header.Segment);
+      W.printString("BlockName", Block.Name);
       W.printString("LinkageName", LinkageName);
       break;
     }
@@ -1077,131 +1101,73 @@ void COFFDumper::printCodeViewSymbolsSub
 
     case S_LABEL32: {
       DictScope S(W, "Label");
-      const LabelSym *Label;
-      error(consumeObject(SymData, Label));
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto LabelOrError = LabelSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!LabelOrError)
+        error(LabelOrError.getError());
+      auto &Label = LabelOrError.get();
 
-      StringRef DisplayName = SymData.split('\0').first;
       StringRef LinkageName;
-      printRelocatedField("CodeOffset", Sec, SectionContents,
-                          &Label->CodeOffset, &LinkageName);
-      W.printHex("Segment", Label->Segment);
-      W.printHex("Flags", Label->Flags);
-      W.printFlags("Flags", Label->Flags, makeArrayRef(ProcSymFlagNames));
-      W.printString("DisplayName", DisplayName);
+      printRelocatedField("CodeOffset", Sec, Label.getRelocationOffset(),
+                          Label.Header.CodeOffset, &LinkageName);
+      W.printHex("Segment", Label.Header.Segment);
+      W.printHex("Flags", Label.Header.Flags);
+      W.printFlags("Flags", Label.Header.Flags, makeArrayRef(ProcSymFlagNames));
+      W.printString("DisplayName", Label.Name);
       W.printString("LinkageName", LinkageName);
       break;
     }
 
     case S_INLINESITE: {
       DictScope S(W, "InlineSite");
-      const InlineSiteSym *InlineSite;
-      error(consumeObject(SymData, InlineSite));
-      W.printHex("PtrParent", InlineSite->PtrParent);
-      W.printHex("PtrEnd", InlineSite->PtrEnd);
-      printTypeIndex("Inlinee", InlineSite->Inlinee);
-
-      auto GetCompressedAnnotation = [&]() -> uint32_t {
-        if (SymData.empty())
-          return -1;
-
-        uint8_t FirstByte = SymData.front();
-        SymData = SymData.drop_front();
-
-        if ((FirstByte & 0x80) == 0x00)
-          return FirstByte;
-
-        if (SymData.empty())
-          return -1;
-
-        uint8_t SecondByte = SymData.front();
-        SymData = SymData.drop_front();
-
-        if ((FirstByte & 0xC0) == 0x80)
-          return ((FirstByte & 0x3F) << 8) | SecondByte;
-
-        if (SymData.empty())
-          return -1;
-
-        uint8_t ThirdByte = SymData.front();
-        SymData = SymData.drop_front();
-
-        if (SymData.empty())
-          return -1;
-
-        uint8_t FourthByte = SymData.front();
-        SymData = SymData.drop_front();
-
-        if ((FirstByte & 0xE0) == 0xC0)
-          return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
-                 (ThirdByte << 8) | FourthByte;
-
-        return -1;
-      };
-      auto DecodeSignedOperand = [](uint32_t Operand) -> int32_t {
-        if (Operand & 1)
-          return -(Operand >> 1);
-        return Operand >> 1;
-      };
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto InlineSiteOrError = InlineSiteSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!InlineSiteOrError)
+        error(InlineSiteOrError.getError());
+      auto &InlineSite = InlineSiteOrError.get();
+
+      W.printHex("PtrParent", InlineSite.Header.PtrParent);
+      W.printHex("PtrEnd", InlineSite.Header.PtrEnd);
+      printTypeIndex("Inlinee", InlineSite.Header.Inlinee);
 
       ListScope BinaryAnnotations(W, "BinaryAnnotations");
-      while (!SymData.empty()) {
-        auto OpCode =
-            static_cast<BinaryAnnotationsOpCode>(GetCompressedAnnotation());
-        switch (OpCode) {
+      for (auto &Annotation : InlineSite.annotations()) {
+        switch (Annotation.OpCode) {
         case BinaryAnnotationsOpCode::Invalid:
           return error(object_error::parse_failed);
         case BinaryAnnotationsOpCode::CodeOffset:
-          W.printHex("CodeOffset", GetCompressedAnnotation());
-          break;
-        case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
-          W.printNumber("ChangeCodeOffsetBase", GetCompressedAnnotation());
-          break;
         case BinaryAnnotationsOpCode::ChangeCodeOffset:
-          W.printHex("ChangeCodeOffset", GetCompressedAnnotation());
-          break;
         case BinaryAnnotationsOpCode::ChangeCodeLength:
-          W.printHex("ChangeCodeLength", GetCompressedAnnotation());
-          break;
-        case BinaryAnnotationsOpCode::ChangeFile:
-          printFileNameForOffset("ChangeFile", GetCompressedAnnotation());
-          break;
-        case BinaryAnnotationsOpCode::ChangeLineOffset:
-          W.printNumber("ChangeLineOffset",
-                        DecodeSignedOperand(GetCompressedAnnotation()));
+          W.printHex(Annotation.Name, Annotation.U1);
           break;
+        case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
         case BinaryAnnotationsOpCode::ChangeLineEndDelta:
-          W.printNumber("ChangeLineEndDelta", GetCompressedAnnotation());
-          break;
         case BinaryAnnotationsOpCode::ChangeRangeKind:
-          W.printNumber("ChangeRangeKind", GetCompressedAnnotation());
-          break;
         case BinaryAnnotationsOpCode::ChangeColumnStart:
-          W.printNumber("ChangeColumnStart", GetCompressedAnnotation());
+        case BinaryAnnotationsOpCode::ChangeColumnEnd:
+          W.printNumber(Annotation.Name, Annotation.U1);
           break;
+        case BinaryAnnotationsOpCode::ChangeLineOffset:
         case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
-          W.printNumber("ChangeColumnEndDelta",
-                        DecodeSignedOperand(GetCompressedAnnotation()));
+          W.printNumber(Annotation.Name, Annotation.S1);
+          break;
+        case BinaryAnnotationsOpCode::ChangeFile:
+          printFileNameForOffset("ChangeFile", Annotation.U1);
           break;
         case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
-          uint32_t Annotation = GetCompressedAnnotation();
-          int32_t LineOffset = DecodeSignedOperand(Annotation >> 4);
-          uint32_t CodeOffset = Annotation & 0xf;
           W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
-                        << W.hex(CodeOffset) << ", LineOffset: " << LineOffset
-                        << "}\n";
+                        << W.hex(Annotation.U1)
+                        << ", LineOffset: " << Annotation.S1 << "}\n";
           break;
         }
         case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
-          uint32_t Length = GetCompressedAnnotation();
-          uint32_t CodeOffset = GetCompressedAnnotation();
           W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
-                        << W.hex(CodeOffset) << ", Length: " << W.hex(Length)
-                        << "}\n";
+                        << W.hex(Annotation.U2)
+                        << ", Length: " << W.hex(Annotation.U1) << "}\n";
           break;
         }
-        case BinaryAnnotationsOpCode::ChangeColumnEnd:
-          W.printNumber("ChangeColumnEnd", GetCompressedAnnotation());
-          break;
         }
       }
       break;
@@ -1227,140 +1193,192 @@ void COFFDumper::printCodeViewSymbolsSub
 
     case S_LOCAL: {
       DictScope S(W, "Local");
-      const LocalSym *Local;
-      error(consumeObject(SymData, Local));
-      printTypeIndex("Type", Local->Type);
-      W.printFlags("Flags", uint16_t(Local->Flags), makeArrayRef(LocalFlags));
-      StringRef VarName = SymData.split('\0').first;
-      W.printString("VarName", VarName);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto LocalOrError = LocalSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!LocalOrError)
+        error(LocalOrError.getError());
+      auto &Local = LocalOrError.get();
+
+      printTypeIndex("Type", Local.Header.Type);
+      W.printFlags("Flags", uint16_t(Local.Header.Flags),
+                   makeArrayRef(LocalFlags));
+      W.printString("VarName", Local.Name);
       break;
     }
 
     case S_DEFRANGE: {
       DictScope S(W, "DefRange");
-      const DefRangeSym *DefRange;
-      error(consumeObject(SymData, DefRange));
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto DefRangeOrError = DefRangeSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!DefRangeOrError)
+        error(DefRangeOrError.getError());
+      auto &DefRange = DefRangeOrError.get();
+
       W.printString(
           "Program",
-          CVStringTable.drop_front(DefRange->Program).split('\0').first);
-      printLocalVariableAddrRange(DefRange->Range, Sec, SectionContents);
-      printLocalVariableAddrGap(SymData);
+          CVStringTable.drop_front(DefRange.Header.Program).split('\0').first);
+      printLocalVariableAddrRange(DefRange.Header.Range, Sec,
+                                  DefRange.getRelocationOffset());
+      printLocalVariableAddrGap(DefRange.Gaps);
       break;
     }
     case S_DEFRANGE_SUBFIELD: {
       DictScope S(W, "DefRangeSubfield");
-      const DefRangeSubfieldSym *DefRangeSubfield;
-      error(consumeObject(SymData, DefRangeSubfield));
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto DefRangeOrError = DefRangeSubfieldSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!DefRangeOrError)
+        error(DefRangeOrError.getError());
+      auto &DefRangeSubfield = DefRangeOrError.get();
+
       W.printString("Program",
-                    CVStringTable.drop_front(DefRangeSubfield->Program)
+                    CVStringTable.drop_front(DefRangeSubfield.Header.Program)
                         .split('\0')
                         .first);
-      W.printNumber("OffsetInParent", DefRangeSubfield->OffsetInParent);
-      printLocalVariableAddrRange(DefRangeSubfield->Range, Sec,
-                                  SectionContents);
-      printLocalVariableAddrGap(SymData);
+      W.printNumber("OffsetInParent", DefRangeSubfield.Header.OffsetInParent);
+      printLocalVariableAddrRange(DefRangeSubfield.Header.Range, Sec,
+                                  DefRangeSubfield.getRelocationOffset());
+      printLocalVariableAddrGap(DefRangeSubfield.Gaps);
       break;
     }
     case S_DEFRANGE_REGISTER: {
       DictScope S(W, "DefRangeRegister");
-      const DefRangeRegisterSym *DefRangeRegister;
-      error(consumeObject(SymData, DefRangeRegister));
-      W.printNumber("Register", DefRangeRegister->Register);
-      W.printNumber("MayHaveNoName", DefRangeRegister->MayHaveNoName);
-      printLocalVariableAddrRange(DefRangeRegister->Range, Sec,
-                                  SectionContents);
-      printLocalVariableAddrGap(SymData);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto DefRangeOrError = DefRangeRegisterSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!DefRangeOrError)
+        error(DefRangeOrError.getError());
+      auto &DefRangeRegisterSym = DefRangeOrError.get();
+
+      W.printNumber("Register", DefRangeRegisterSym.Header.Register);
+      W.printNumber("MayHaveNoName", DefRangeRegisterSym.Header.MayHaveNoName);
+      printLocalVariableAddrRange(DefRangeRegisterSym.Header.Range, Sec,
+                                  DefRangeRegisterSym.getRelocationOffset());
+      printLocalVariableAddrGap(DefRangeRegisterSym.Gaps);
       break;
     }
     case S_DEFRANGE_SUBFIELD_REGISTER: {
       DictScope S(W, "DefRangeSubfieldRegister");
-      const DefRangeSubfieldRegisterSym *DefRangeSubfieldRegisterSym;
-      error(consumeObject(SymData, DefRangeSubfieldRegisterSym));
-      W.printNumber("Register", DefRangeSubfieldRegisterSym->Register);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto DefRangeOrError = DefRangeSubfieldRegisterSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!DefRangeOrError)
+        error(DefRangeOrError.getError());
+      auto &DefRangeSubfieldRegister = DefRangeOrError.get();
+      W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
       W.printNumber("MayHaveNoName",
-                    DefRangeSubfieldRegisterSym->MayHaveNoName);
+                    DefRangeSubfieldRegister.Header.MayHaveNoName);
       W.printNumber("OffsetInParent",
-                    DefRangeSubfieldRegisterSym->OffsetInParent);
-      printLocalVariableAddrRange(DefRangeSubfieldRegisterSym->Range, Sec,
-                                  SectionContents);
-      printLocalVariableAddrGap(SymData);
+                    DefRangeSubfieldRegister.Header.OffsetInParent);
+      printLocalVariableAddrRange(
+          DefRangeSubfieldRegister.Header.Range, Sec,
+          DefRangeSubfieldRegister.getRelocationOffset());
+      printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
       break;
     }
     case S_DEFRANGE_FRAMEPOINTER_REL: {
       DictScope S(W, "DefRangeFramePointerRel");
-      const DefRangeFramePointerRelSym *DefRangeFramePointerRel;
-      error(consumeObject(SymData, DefRangeFramePointerRel));
-      W.printNumber("Offset", DefRangeFramePointerRel->Offset);
-      printLocalVariableAddrRange(DefRangeFramePointerRel->Range, Sec,
-                                  SectionContents);
-      printLocalVariableAddrGap(SymData);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto DefRangeOrError = DefRangeFramePointerRelSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!DefRangeOrError)
+        error(DefRangeOrError.getError());
+      auto &DefRangeFramePointerRel = DefRangeOrError.get();
+      W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
+      printLocalVariableAddrRange(
+          DefRangeFramePointerRel.Header.Range, Sec,
+          DefRangeFramePointerRel.getRelocationOffset());
+      printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
       break;
     }
     case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: {
       DictScope S(W, "DefRangeFramePointerRelFullScope");
-      const DefRangeFramePointerRelFullScopeSym
-          *DefRangeFramePointerRelFullScope;
-      error(consumeObject(SymData, DefRangeFramePointerRelFullScope));
-      W.printNumber("Offset", DefRangeFramePointerRelFullScope->Offset);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto DefRangeOrError = DefRangeFramePointerRelFullScopeSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!DefRangeOrError)
+        error(DefRangeOrError.getError());
+      auto &DefRangeFramePointerRelFullScope = DefRangeOrError.get();
+      W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
       break;
     }
     case S_DEFRANGE_REGISTER_REL: {
       DictScope S(W, "DefRangeRegisterRel");
-      const DefRangeRegisterRelSym *DefRangeRegisterRel;
-      error(consumeObject(SymData, DefRangeRegisterRel));
-      W.printNumber("BaseRegister", DefRangeRegisterRel->BaseRegister);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto DefRangeOrError = DefRangeRegisterRelSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!DefRangeOrError)
+        error(DefRangeOrError.getError());
+      auto &DefRangeRegisterRel = DefRangeOrError.get();
+
+      W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
       W.printBoolean("HasSpilledUDTMember",
-                     DefRangeRegisterRel->hasSpilledUDTMember());
-      W.printNumber("OffsetInParent", DefRangeRegisterRel->offsetInParent());
+                     DefRangeRegisterRel.hasSpilledUDTMember());
+      W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
       W.printNumber("BasePointerOffset",
-                    DefRangeRegisterRel->BasePointerOffset);
-      printLocalVariableAddrRange(DefRangeRegisterRel->Range, Sec,
-                                  SectionContents);
-      printLocalVariableAddrGap(SymData);
+                    DefRangeRegisterRel.Header.BasePointerOffset);
+      printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range, Sec,
+                                  DefRangeRegisterRel.getRelocationOffset());
+      printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
       break;
     }
 
     case S_CALLSITEINFO: {
       DictScope S(W, "CallSiteInfo");
-      const CallSiteInfoSym *CallSiteInfo;
-      error(consumeObject(SymData, CallSiteInfo));
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto CallSiteOrError = CallSiteInfoSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!CallSiteOrError)
+        error(CallSiteOrError.getError());
+      auto &CallSiteInfo = CallSiteOrError.get();
 
       StringRef LinkageName;
-      printRelocatedField("CodeOffset", Sec, SectionContents,
-                          &CallSiteInfo->CodeOffset, &LinkageName);
-      W.printHex("Segment", CallSiteInfo->Segment);
-      W.printHex("Reserved", CallSiteInfo->Reserved);
-      printTypeIndex("Type", CallSiteInfo->Type);
+      printRelocatedField("CodeOffset", Sec, CallSiteInfo.getRelocationOffset(),
+                          CallSiteInfo.Header.CodeOffset, &LinkageName);
+      W.printHex("Segment", CallSiteInfo.Header.Segment);
+      W.printHex("Reserved", CallSiteInfo.Header.Reserved);
+      printTypeIndex("Type", CallSiteInfo.Header.Type);
       W.printString("LinkageName", LinkageName);
       break;
     }
 
     case S_HEAPALLOCSITE: {
       DictScope S(W, "HeapAllocationSite");
-      const HeapAllocationSiteSym *HeapAllocationSite;
-      error(consumeObject(SymData, HeapAllocationSite));
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto HeapAllocSiteOrError = HeapAllocationSiteSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!HeapAllocSiteOrError)
+        error(HeapAllocSiteOrError.getError());
+      auto &HeapAllocSite = HeapAllocSiteOrError.get();
 
       StringRef LinkageName;
-      printRelocatedField("CodeOffset", Sec, SectionContents,
-                          &HeapAllocationSite->CodeOffset, &LinkageName);
-      W.printHex("Segment", HeapAllocationSite->Segment);
+      printRelocatedField("CodeOffset", Sec,
+                          HeapAllocSite.getRelocationOffset(),
+                          HeapAllocSite.Header.CodeOffset, &LinkageName);
+      W.printHex("Segment", HeapAllocSite.Header.Segment);
       W.printHex("CallInstructionSize",
-                 HeapAllocationSite->CallInstructionSize);
-      printTypeIndex("Type", HeapAllocationSite->Type);
+                 HeapAllocSite.Header.CallInstructionSize);
+      printTypeIndex("Type", HeapAllocSite.Header.Type);
       W.printString("LinkageName", LinkageName);
       break;
     }
 
     case S_FRAMECOOKIE: {
       DictScope S(W, "FrameCookie");
-      const FrameCookieSym *FrameCookie;
-      error(consumeObject(SymData, FrameCookie));
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto FrameCookieOrError = FrameCookieSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!FrameCookieOrError)
+        error(FrameCookieOrError.getError());
+      auto &FrameCookie = FrameCookieOrError.get();
 
       StringRef LinkageName;
-      printRelocatedField("CodeOffset", Sec, SectionContents,
-                          &FrameCookie->CodeOffset, &LinkageName);
-      W.printHex("Register", FrameCookie->Register);
-      W.printEnum("CookieKind", uint16_t(FrameCookie->CookieKind),
+      printRelocatedField("CodeOffset", Sec, FrameCookie.getRelocationOffset(),
+                          FrameCookie.Header.CodeOffset, &LinkageName);
+      W.printHex("Register", FrameCookie.Header.Register);
+      W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
                   makeArrayRef(FrameCookieKinds));
       break;
     }
@@ -1370,15 +1388,18 @@ void COFFDumper::printCodeViewSymbolsSub
     case S_LMANDATA:
     case S_GMANDATA: {
       DictScope S(W, "DataSym");
-      const DataSym *Data;
-      error(consumeObject(SymData, Data));
+      ArrayRef<uint8_t> SymBytes(SymData.bytes_begin(), SymData.bytes_end());
+      auto DataOrError = DataSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, SymBytes);
+      if (!DataOrError)
+        error(DataOrError.getError());
+      auto &Data = DataOrError.get();
 
-      StringRef DisplayName = SymData.split('\0').first;
       StringRef LinkageName;
-      printRelocatedField("DataOffset", Sec, SectionContents, &Data->DataOffset,
-                          &LinkageName);
-      printTypeIndex("Type", Data->Type);
-      W.printString("DisplayName", DisplayName);
+      printRelocatedField("DataOffset", Sec, Data.getRelocationOffset(),
+                          Data.Header.DataOffset, &LinkageName);
+      printTypeIndex("Type", Data.Header.Type);
+      W.printString("DisplayName", Data.Name);
       W.printString("LinkageName", LinkageName);
       break;
     }
@@ -1386,130 +1407,161 @@ void COFFDumper::printCodeViewSymbolsSub
     case S_LTHREAD32:
     case S_GTHREAD32: {
       DictScope S(W, "ThreadLocalDataSym");
-      const ThreadLocalDataSym *Data;
-      error(consumeObject(SymData, Data));
+      ArrayRef<uint8_t> SymBytes(SymData.bytes_begin(), SymData.bytes_end());
+      auto ThreadLocalDataOrError = ThreadLocalDataSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, SymBytes);
+      if (!ThreadLocalDataOrError)
+        error(ThreadLocalDataOrError.getError());
+      auto &Data = ThreadLocalDataOrError.get();
 
-      StringRef DisplayName = SymData.split('\0').first;
       StringRef LinkageName;
-      printRelocatedField("DataOffset", Sec, SectionContents, &Data->DataOffset,
-                          &LinkageName);
-      printTypeIndex("Type", Data->Type);
-      W.printString("DisplayName", DisplayName);
+      printRelocatedField("DataOffset", Sec, Data.getRelocationOffset(),
+                          Data.Header.DataOffset, &LinkageName);
+      printTypeIndex("Type", Data.Header.Type);
+      W.printString("DisplayName", Data.Name);
       W.printString("LinkageName", LinkageName);
       break;
     }
 
     case S_OBJNAME: {
       DictScope S(W, "ObjectName");
-      const ObjNameSym *ObjName;
-      error(consumeObject(SymData, ObjName));
-      W.printHex("Signature", ObjName->Signature);
-      StringRef ObjectName = SymData.split('\0').first;
-      W.printString("ObjectName", ObjectName);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto ObjNameOrError = ObjNameSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!ObjNameOrError)
+        error(ObjNameOrError.getError());
+      auto &ObjName = ObjNameOrError.get();
+      W.printHex("Signature", ObjName.Header.Signature);
+      W.printString("ObjectName", ObjName.Name);
       break;
     }
 
     case S_COMPILE3: {
       DictScope S(W, "CompilerFlags");
-      const CompileSym3 *CompFlags;
-      error(consumeObject(SymData, CompFlags));
-      W.printEnum("Language", CompFlags->getLanguage(),
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto Compile3OrError = CompileSym3::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!Compile3OrError)
+        error(Compile3OrError.getError());
+      auto &Compile3 = Compile3OrError.get();
+
+      W.printEnum("Language", Compile3.Header.getLanguage(),
                   makeArrayRef(SourceLanguages));
-      W.printFlags("Flags", CompFlags->flags & ~0xff,
+      W.printFlags("Flags", Compile3.Header.flags & ~0xff,
                    makeArrayRef(CompileSym3FlagNames));
-      W.printEnum("Machine", unsigned(CompFlags->Machine),
+      W.printEnum("Machine", unsigned(Compile3.Header.Machine),
                   makeArrayRef(CPUTypeNames));
       std::string FrontendVersion;
       {
         raw_string_ostream Out(FrontendVersion);
-        Out << CompFlags->VersionFrontendMajor << '.'
-            << CompFlags->VersionFrontendMinor << '.'
-            << CompFlags->VersionFrontendBuild << '.'
-            << CompFlags->VersionFrontendQFE;
+        Out << Compile3.Header.VersionFrontendMajor << '.'
+            << Compile3.Header.VersionFrontendMinor << '.'
+            << Compile3.Header.VersionFrontendBuild << '.'
+            << Compile3.Header.VersionFrontendQFE;
       }
       std::string BackendVersion;
       {
         raw_string_ostream Out(BackendVersion);
-        Out << CompFlags->VersionBackendMajor << '.'
-            << CompFlags->VersionBackendMinor << '.'
-            << CompFlags->VersionBackendBuild << '.'
-            << CompFlags->VersionBackendQFE;
+        Out << Compile3.Header.VersionBackendMajor << '.'
+            << Compile3.Header.VersionBackendMinor << '.'
+            << Compile3.Header.VersionBackendBuild << '.'
+            << Compile3.Header.VersionBackendQFE;
       }
       W.printString("FrontendVersion", FrontendVersion);
       W.printString("BackendVersion", BackendVersion);
-      StringRef VersionName = SymData.split('\0').first;
-      W.printString("VersionName", VersionName);
+      W.printString("VersionName", Compile3.Version);
       break;
     }
 
     case S_FRAMEPROC: {
       DictScope S(W, "FrameProc");
-      const FrameProcSym *FrameProc;
-      error(consumeObject(SymData, FrameProc));
-      W.printHex("TotalFrameBytes", FrameProc->TotalFrameBytes);
-      W.printHex("PaddingFrameBytes", FrameProc->PaddingFrameBytes);
-      W.printHex("OffsetToPadding", FrameProc->OffsetToPadding);
-      W.printHex("BytesOfCalleeSavedRegisters", FrameProc->BytesOfCalleeSavedRegisters);
-      W.printHex("OffsetOfExceptionHandler", FrameProc->OffsetOfExceptionHandler);
-      W.printHex("SectionIdOfExceptionHandler", FrameProc->SectionIdOfExceptionHandler);
-      W.printFlags("Flags", FrameProc->Flags, makeArrayRef(FrameProcSymFlags));
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto FrameProcOrError = FrameProcSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!FrameProcOrError)
+        error(FrameProcOrError.getError());
+      auto &FrameProc = FrameProcOrError.get();
+      W.printHex("TotalFrameBytes", FrameProc.Header.TotalFrameBytes);
+      W.printHex("PaddingFrameBytes", FrameProc.Header.PaddingFrameBytes);
+      W.printHex("OffsetToPadding", FrameProc.Header.OffsetToPadding);
+      W.printHex("BytesOfCalleeSavedRegisters",
+                 FrameProc.Header.BytesOfCalleeSavedRegisters);
+      W.printHex("OffsetOfExceptionHandler",
+                 FrameProc.Header.OffsetOfExceptionHandler);
+      W.printHex("SectionIdOfExceptionHandler",
+                 FrameProc.Header.SectionIdOfExceptionHandler);
+      W.printFlags("Flags", FrameProc.Header.Flags,
+                   makeArrayRef(FrameProcSymFlags));
       break;
     }
 
     case S_UDT:
     case S_COBOLUDT: {
       DictScope S(W, "UDT");
-      const UDTSym *UDT;
-      error(consumeObject(SymData, UDT));
-      printTypeIndex("Type", UDT->Type);
-      StringRef UDTName = SymData.split('\0').first;
-      W.printString("UDTName", UDTName);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto UdtOrError = UDTSym::deserialize(static_cast<SymbolRecordKind>(Kind),
+                                            RecordOffset, Data);
+      if (!UdtOrError)
+        error(UdtOrError.getError());
+      auto &UDT = UdtOrError.get();
+      printTypeIndex("Type", UDT.Header.Type);
+      W.printString("UDTName", UDT.Name);
       break;
     }
 
     case S_BPREL32: {
       DictScope S(W, "BPRelativeSym");
-      const BPRelativeSym *BPRel;
-      error(consumeObject(SymData, BPRel));
-      W.printNumber("Offset", BPRel->Offset);
-      printTypeIndex("Type", BPRel->Type);
-      StringRef VarName = SymData.split('\0').first;
-      W.printString("VarName", VarName);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto BPRelOrError = BPRelativeSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!BPRelOrError)
+        error(BPRelOrError.getError());
+      auto &BPRel = BPRelOrError.get();
+      W.printNumber("Offset", BPRel.Header.Offset);
+      printTypeIndex("Type", BPRel.Header.Type);
+      W.printString("VarName", BPRel.Name);
       break;
     }
 
     case S_REGREL32: {
       DictScope S(W, "RegRelativeSym");
-      const RegRelativeSym *RegRel;
-      error(consumeObject(SymData, RegRel));
-      W.printHex("Offset", RegRel->Offset);
-      printTypeIndex("Type", RegRel->Type);
-      W.printHex("Register", RegRel->Register);
-      StringRef VarName = SymData.split('\0').first;
-      W.printString("VarName", VarName);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto RegRelOrError = RegRelativeSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!RegRelOrError)
+        error(RegRelOrError.getError());
+      auto &RegRel = RegRelOrError.get();
+      W.printHex("Offset", RegRel.Header.Offset);
+      printTypeIndex("Type", RegRel.Header.Type);
+      W.printHex("Register", RegRel.Header.Register);
+      W.printString("VarName", RegRel.Name);
       break;
     }
 
     case S_BUILDINFO: {
       DictScope S(W, "BuildInfo");
-      const BuildInfoSym *BuildInfo;
-      error(consumeObject(SymData, BuildInfo));
-      W.printNumber("BuildId", BuildInfo->BuildId);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto BuildInfoOrError = BuildInfoSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!BuildInfoOrError)
+        error(BuildInfoOrError.getError());
+      auto &BuildInfo = BuildInfoOrError.get();
+      W.printNumber("BuildId", BuildInfo.Header.BuildId);
       break;
     }
 
     case S_CONSTANT:
     case S_MANCONSTANT: {
       DictScope S(W, "Constant");
-      const ConstantSym *Constant;
-      error(consumeObject(SymData, Constant));
-      printTypeIndex("Type", Constant->Type);
-      APSInt Value;
-      if (consume(SymData, Value))
-        error(object_error::parse_failed);
-      W.printNumber("Value", Value);
-      StringRef Name = SymData.split('\0').first;
-      W.printString("Name", Name);
+      ArrayRef<uint8_t> Data(SymData.bytes_begin(), SymData.bytes_end());
+      auto ConstantOrError = ConstantSym::deserialize(
+          static_cast<SymbolRecordKind>(Kind), RecordOffset, Data);
+      if (!ConstantOrError)
+        error(ConstantOrError.getError());
+      auto &Constant = ConstantOrError.get();
+      printTypeIndex("Type", Constant.Header.Type);
+      W.printNumber("Value", Constant.Value);
+      W.printString("Name", Constant.Name);
       break;
     }
 
@@ -1583,20 +1635,19 @@ void COFFDumper::printCodeViewInlineeLin
 
 void COFFDumper::printLocalVariableAddrRange(
     const LocalVariableAddrRange &Range, const coff_section *Sec,
-    StringRef SectionContents) {
+    uint32_t RelocationOffset) {
   DictScope S(W, "LocalVariableAddrRange");
-  printRelocatedField("OffsetStart", Sec, SectionContents, &Range.OffsetStart);
+  printRelocatedField("OffsetStart", Sec, RelocationOffset, Range.OffsetStart);
   W.printHex("ISectStart", Range.ISectStart);
   W.printHex("Range", Range.Range);
 }
 
-void COFFDumper::printLocalVariableAddrGap(StringRef &SymData) {
-  while (!SymData.empty()) {
-    const LocalVariableAddrGap *Gap;
-    error(consumeObject(SymData, Gap));
+void COFFDumper::printLocalVariableAddrGap(
+    ArrayRef<LocalVariableAddrGap> Gaps) {
+  for (auto &Gap : Gaps) {
     ListScope S(W, "LocalVariableAddrGap");
-    W.printHex("GapStartOffset", Gap->GapStartOffset);
-    W.printHex("Range", Gap->Range);
+    W.printHex("GapStartOffset", Gap.GapStartOffset);
+    W.printHex("Range", Gap.Range);
   }
 }
 




More information about the llvm-commits mailing list