Home | History | Annotate | Download | only in CodeView
      1 //===- TypeDeserializer.h ---------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
     11 #define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
     12 
     13 #include "llvm/ADT/ArrayRef.h"
     14 #include "llvm/ADT/STLExtras.h"
     15 #include "llvm/DebugInfo/CodeView/CodeView.h"
     16 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
     17 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
     18 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
     19 #include "llvm/Support/BinaryByteStream.h"
     20 #include "llvm/Support/BinaryStreamReader.h"
     21 #include "llvm/Support/Error.h"
     22 #include <cassert>
     23 #include <cstdint>
     24 #include <memory>
     25 
     26 namespace llvm {
     27 namespace codeview {
     28 
     29 class TypeDeserializer : public TypeVisitorCallbacks {
     30   struct MappingInfo {
     31     explicit MappingInfo(ArrayRef<uint8_t> RecordData)
     32         : Stream(RecordData, llvm::support::little), Reader(Stream),
     33           Mapping(Reader) {}
     34 
     35     BinaryByteStream Stream;
     36     BinaryStreamReader Reader;
     37     TypeRecordMapping Mapping;
     38   };
     39 
     40 public:
     41   TypeDeserializer() = default;
     42 
     43   template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
     44     Record.Kind = static_cast<TypeRecordKind>(CVT.kind());
     45     MappingInfo I(CVT.content());
     46     if (auto EC = I.Mapping.visitTypeBegin(CVT))
     47       return EC;
     48     if (auto EC = I.Mapping.visitKnownRecord(CVT, Record))
     49       return EC;
     50     if (auto EC = I.Mapping.visitTypeEnd(CVT))
     51       return EC;
     52     return Error::success();
     53   }
     54 
     55   Error visitTypeBegin(CVType &Record) override {
     56     assert(!Mapping && "Already in a type mapping!");
     57     Mapping = llvm::make_unique<MappingInfo>(Record.content());
     58     return Mapping->Mapping.visitTypeBegin(Record);
     59   }
     60 
     61   Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
     62     return visitTypeBegin(Record);
     63   }
     64 
     65   Error visitTypeEnd(CVType &Record) override {
     66     assert(Mapping && "Not in a type mapping!");
     67     auto EC = Mapping->Mapping.visitTypeEnd(Record);
     68     Mapping.reset();
     69     return EC;
     70   }
     71 
     72 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
     73   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override {         \
     74     return visitKnownRecordImpl<Name##Record>(CVR, Record);                    \
     75   }
     76 #define MEMBER_RECORD(EnumName, EnumVal, Name)
     77 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
     78 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
     79 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
     80 
     81 private:
     82   template <typename RecordType>
     83   Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) {
     84     return Mapping->Mapping.visitKnownRecord(CVR, Record);
     85   }
     86 
     87   std::unique_ptr<MappingInfo> Mapping;
     88 };
     89 
     90 class FieldListDeserializer : public TypeVisitorCallbacks {
     91   struct MappingInfo {
     92     explicit MappingInfo(BinaryStreamReader &R)
     93         : Reader(R), Mapping(Reader), StartOffset(0) {}
     94 
     95     BinaryStreamReader &Reader;
     96     TypeRecordMapping Mapping;
     97     uint32_t StartOffset;
     98   };
     99 
    100 public:
    101   explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
    102     CVType FieldList;
    103     FieldList.Type = TypeLeafKind::LF_FIELDLIST;
    104     consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
    105   }
    106 
    107   ~FieldListDeserializer() override {
    108     CVType FieldList;
    109     FieldList.Type = TypeLeafKind::LF_FIELDLIST;
    110     consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
    111   }
    112 
    113   Error visitMemberBegin(CVMemberRecord &Record) override {
    114     Mapping.StartOffset = Mapping.Reader.getOffset();
    115     return Mapping.Mapping.visitMemberBegin(Record);
    116   }
    117 
    118   Error visitMemberEnd(CVMemberRecord &Record) override {
    119     if (auto EC = Mapping.Mapping.visitMemberEnd(Record))
    120       return EC;
    121     return Error::success();
    122   }
    123 
    124 #define TYPE_RECORD(EnumName, EnumVal, Name)
    125 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
    126   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
    127     return visitKnownMemberImpl<Name##Record>(CVR, Record);                    \
    128   }
    129 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
    130 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
    131 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
    132 
    133 private:
    134   template <typename RecordType>
    135   Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
    136     if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record))
    137       return EC;
    138 
    139     uint32_t EndOffset = Mapping.Reader.getOffset();
    140     uint32_t RecordLength = EndOffset - Mapping.StartOffset;
    141     Mapping.Reader.setOffset(Mapping.StartOffset);
    142     if (auto EC = Mapping.Reader.readBytes(CVR.Data, RecordLength))
    143       return EC;
    144     assert(Mapping.Reader.getOffset() == EndOffset);
    145     return Error::success();
    146   }
    147   MappingInfo Mapping;
    148 };
    149 
    150 } // end namespace codeview
    151 } // end namespace llvm
    152 
    153 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
    154