Index: include/llvm/DebugInfo/CodeView/RecordSerialization.h =================================================================== --- include/llvm/DebugInfo/CodeView/RecordSerialization.h +++ include/llvm/DebugInfo/CodeView/RecordSerialization.h @@ -114,8 +114,8 @@ U Func; }; -template struct serialize_array_tail_impl { - serialize_array_tail_impl(std::vector &Item) : Item(Item) {} +template struct serialize_vector_tail_impl { + serialize_vector_tail_impl(std::vector &Item) : Item(Item) {} std::error_code deserialize(ArrayRef &Data) const { T Field; @@ -131,6 +131,18 @@ std::vector &Item; }; +template struct serialize_arrayref_tail_impl { + serialize_arrayref_tail_impl(ArrayRef &Item) : Item(Item) {} + + std::error_code deserialize(ArrayRef &Data) const { + uint32_t Count = Data.size() / sizeof(T); + Item = ArrayRef(reinterpret_cast(Data.begin()), Count); + return std::error_code(); + } + + ArrayRef &Item; +}; + template struct serialize_numeric_impl { serialize_numeric_impl(T &Item) : Item(Item) {} @@ -147,8 +159,13 @@ } template -serialize_array_tail_impl serialize_array_tail(std::vector &Item) { - return serialize_array_tail_impl(Item); +serialize_vector_tail_impl serialize_array_tail(std::vector &Item) { + return serialize_vector_tail_impl(Item); +} + +template +serialize_arrayref_tail_impl serialize_array_tail(ArrayRef &Item) { + return serialize_arrayref_tail_impl(Item); } template serialize_numeric_impl serialize_numeric(T &Item) { @@ -185,7 +202,13 @@ template std::error_code consume(ArrayRef &Data, - const serialize_array_tail_impl &Item) { + const serialize_vector_tail_impl &Item) { + return Item.deserialize(Data); +} + +template +std::error_code consume(ArrayRef &Data, + const serialize_arrayref_tail_impl &Item) { return Item.deserialize(Data); } Index: include/llvm/DebugInfo/CodeView/SymbolRecord.h =================================================================== --- include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -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::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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 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(); + 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 &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 &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(Op); + switch (Result.OpCode) { + case BinaryAnnotationsOpCode::Invalid: + Result.Name = "Invalid"; + Next = ArrayRef(); + 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 Current; + ArrayRef Data; + ArrayRef 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 Annotations) + : SymbolRecord(SymbolRecordKind::InlineSiteSym), + RecordOffset(RecordOffset), Header(*H), Annotations(Annotations) {} + + static ErrorOr deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + ArrayRef Annotations; + CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Annotations)); + + return InlineSiteSym(RecordOffset, H, Annotations); + } + + llvm::iterator_range annotations() const { + return llvm::make_range(BinaryAnnotationIterator(Annotations), + BinaryAnnotationIterator()); + } + + uint32_t RecordOffset; + Hdr Header; + +private: + ArrayRef 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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 @@ 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 Gaps) + : SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset), + Header(*H), Gaps(Gaps) {} + + static ErrorOr deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + ArrayRef 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 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 Gaps) + : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym), + RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {} + + static ErrorOr deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + ArrayRef 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 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 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 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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + ArrayRef 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 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 Gaps) + : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym), + RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {} + + DefRangeSubfieldRegisterSym(uint16_t Register, uint16_t MayHaveNoName, + uint32_t OffsetInParent, + ArrayRef Gaps) + : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym), + RecordOffset(0), Gaps(Gaps) { + Header.Register = Register; + Header.MayHaveNoName = MayHaveNoName; + Header.OffsetInParent = OffsetInParent; + } + + static ErrorOr + deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + ArrayRef 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 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[]; + }; -// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE -struct DefRangeFramePointerRelFullScopeSym { - little32_t Offset; // Offset from the frame pointer register + DefRangeFramePointerRelSym(uint32_t RecordOffset, const Hdr *H, + ArrayRef Gaps) + : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym), + RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {} + + static ErrorOr + deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + ArrayRef 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 Gaps; }; // S_DEFRANGE_REGISTER_REL -struct DefRangeRegisterRelSym { - ulittle16_t BaseRegister; - ulittle16_t Flags; - little32_t BasePointerOffset; - LocalVariableAddrRange Range; - // LocalVariableAddrGap Gaps[]; - - bool hasSpilledUDTMember() const { return Flags & 1; } - uint16_t offsetInParent() const { return Flags >> 4; } +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 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 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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + ArrayRef 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 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 + deserialize(SymbolRecordKind Kind, uint32_t RecordOffset, + ArrayRef &Data) { + const Hdr *H = nullptr; + CV_DESERIALIZE(Data, H); + + return DefRangeFramePointerRelFullScopeSym(RecordOffset, H); + } + + 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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 deserialize(SymbolRecordKind Kind, + uint32_t RecordOffset, + ArrayRef &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 SymbolIterator; Index: lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -734,25 +734,25 @@ continue; if (DefRange.InMemory) { - DefRangeRegisterRelSym Sym{}; + DefRangeRegisterRelSym Sym(DefRange.CVRegister, 0, DefRange.DataOffset, 0, + 0, 0, ArrayRef()); 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(&SymKind), sizeof(SymKind)); - BytePrefix += StringRef(reinterpret_cast(&Sym), - sizeof(Sym) - sizeof(LocalVariableAddrRange)); + BytePrefix += + StringRef(reinterpret_cast(&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()); ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER); - Sym.Register = DefRange.CVRegister; - Sym.MayHaveNoName = 0; // Unclear what matters here. BytePrefix += StringRef(reinterpret_cast(&SymKind), sizeof(SymKind)); - BytePrefix += StringRef(reinterpret_cast(&Sym), - sizeof(Sym) - sizeof(LocalVariableAddrRange)); + BytePrefix += + StringRef(reinterpret_cast(&Sym.Header), + sizeof(Sym.Header) - sizeof(LocalVariableAddrRange)); } OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix); } Index: tools/llvm-readobj/COFFDumper.cpp =================================================================== --- tools/llvm-readobj/COFFDumper.cpp +++ tools/llvm-readobj/COFFDumper.cpp @@ -98,8 +98,8 @@ } void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, const coff_section *Sec, - StringRef SectionContents); - void printLocalVariableAddrGap(StringRef &SymData); + uint32_t RelocationOffset); + void printLocalVariableAddrGap(ArrayRef Gaps); void printCodeViewSymbolsSubsection(StringRef Subsection, const SectionRef &Section, @@ -110,6 +110,10 @@ 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 @@ } 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 @@ StringRef OrigSymData = SymData; Data = Data.drop_front(Rec->RecordLen - 2); + uint32_t RecordOffset = SymData.data() - SectionContents.data(); SymbolKind Kind = static_cast(uint16_t(Rec->RecordKind)); switch (Kind) { @@ -1021,26 +1037,31 @@ case S_LPROC32_DPC: case S_LPROC32_DPC_ID: { DictScope S(W, "ProcStart"); - const ProcSym *Proc; - error(consumeObject(SymData, Proc)); + ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); + auto ProcOrError = ProcSym::deserialize( + static_cast(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(Proc.Header.Flags), + makeArrayRef(ProcSymFlagNames)); + W.printString("DisplayName", Proc.Name); W.printString("LinkageName", LinkageName); break; } @@ -1053,18 +1074,21 @@ case S_BLOCK32: { DictScope S(W, "BlockStart"); - const BlockSym *Block; - error(consumeObject(SymData, Block)); + ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); + auto BlockOrError = BlockSym::deserialize( + static_cast(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 @@ case S_LABEL32: { DictScope S(W, "Label"); - const LabelSym *Label; - error(consumeObject(SymData, Label)); + ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); + auto LabelOrError = LabelSym::deserialize( + static_cast(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(); + ArrayRef Data(SymData.bytes_begin(), SymData.bytes_end()); + auto InlineSiteOrError = InlineSiteSym::deserialize( + static_cast(Kind), RecordOffset, Data); + if (!InlineSiteOrError) + error(InlineSiteOrError.getError()); + auto &InlineSite = InlineSiteOrError.get(); - 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; - }; + 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(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 @@ 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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto LocalOrError = LocalSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto DefRangeOrError = DefRangeSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto DefRangeOrError = DefRangeSubfieldSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto DefRangeOrError = DefRangeRegisterSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto DefRangeOrError = DefRangeSubfieldRegisterSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto DefRangeOrError = DefRangeFramePointerRelSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto DefRangeOrError = DefRangeFramePointerRelFullScopeSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto DefRangeOrError = DefRangeRegisterRelSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto CallSiteOrError = CallSiteInfoSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto HeapAllocSiteOrError = HeapAllocationSiteSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto FrameCookieOrError = FrameCookieSym::deserialize( + static_cast(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 @@ case S_LMANDATA: case S_GMANDATA: { DictScope S(W, "DataSym"); - const DataSym *Data; - error(consumeObject(SymData, Data)); + ArrayRef SymBytes(SymData.bytes_begin(), SymData.bytes_end()); + auto DataOrError = DataSym::deserialize( + static_cast(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 @@ case S_LTHREAD32: case S_GTHREAD32: { DictScope S(W, "ThreadLocalDataSym"); - const ThreadLocalDataSym *Data; - error(consumeObject(SymData, Data)); + ArrayRef SymBytes(SymData.bytes_begin(), SymData.bytes_end()); + auto ThreadLocalDataOrError = ThreadLocalDataSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto ObjNameOrError = ObjNameSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto Compile3OrError = CompileSym3::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto FrameProcOrError = FrameProcSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto UdtOrError = UDTSym::deserialize(static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto BPRelOrError = BPRelativeSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto RegRelOrError = RegRelativeSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto BuildInfoOrError = BuildInfoSym::deserialize( + static_cast(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 Data(SymData.bytes_begin(), SymData.bytes_end()); + auto ConstantOrError = ConstantSym::deserialize( + static_cast(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::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 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); } }