Home | History | Annotate | Line # | Download | only in CodeView
      1 //===- SymbolDeserializer.h -------------------------------------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLDESERIALIZER_H
     10 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDESERIALIZER_H
     11 
     12 #include "llvm/ADT/ArrayRef.h"
     13 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
     14 #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
     15 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
     16 #include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
     17 #include "llvm/Support/BinaryByteStream.h"
     18 #include "llvm/Support/BinaryStreamReader.h"
     19 #include "llvm/Support/Error.h"
     20 
     21 namespace llvm {
     22 namespace codeview {
     23 class SymbolVisitorDelegate;
     24 class SymbolDeserializer : public SymbolVisitorCallbacks {
     25   struct MappingInfo {
     26     MappingInfo(ArrayRef<uint8_t> RecordData, CodeViewContainer Container)
     27         : Stream(RecordData, llvm::support::little), Reader(Stream),
     28           Mapping(Reader, Container) {}
     29 
     30     BinaryByteStream Stream;
     31     BinaryStreamReader Reader;
     32     SymbolRecordMapping Mapping;
     33   };
     34 
     35 public:
     36   template <typename T> static Error deserializeAs(CVSymbol Symbol, T &Record) {
     37     // If we're just deserializing one record, then don't worry about alignment
     38     // as there's nothing that comes after.
     39     SymbolDeserializer S(nullptr, CodeViewContainer::ObjectFile);
     40     if (auto EC = S.visitSymbolBegin(Symbol))
     41       return EC;
     42     if (auto EC = S.visitKnownRecord(Symbol, Record))
     43       return EC;
     44     if (auto EC = S.visitSymbolEnd(Symbol))
     45       return EC;
     46     return Error::success();
     47   }
     48   template <typename T> static Expected<T> deserializeAs(CVSymbol Symbol) {
     49     T Record(static_cast<SymbolRecordKind>(Symbol.kind()));
     50     if (auto EC = deserializeAs<T>(Symbol, Record))
     51       return std::move(EC);
     52     return Record;
     53   }
     54 
     55   explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate,
     56                               CodeViewContainer Container)
     57       : Delegate(Delegate), Container(Container) {}
     58 
     59   Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override {
     60     return visitSymbolBegin(Record);
     61   }
     62 
     63   Error visitSymbolBegin(CVSymbol &Record) override {
     64     assert(!Mapping && "Already in a symbol mapping!");
     65     Mapping = std::make_unique<MappingInfo>(Record.content(), Container);
     66     return Mapping->Mapping.visitSymbolBegin(Record);
     67   }
     68   Error visitSymbolEnd(CVSymbol &Record) override {
     69     assert(Mapping && "Not in a symbol mapping!");
     70     auto EC = Mapping->Mapping.visitSymbolEnd(Record);
     71     Mapping.reset();
     72     return EC;
     73   }
     74 
     75 #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
     76   Error visitKnownRecord(CVSymbol &CVR, Name &Record) override {               \
     77     return visitKnownRecordImpl(CVR, Record);                                  \
     78   }
     79 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
     80 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
     81 
     82 private:
     83   template <typename T> Error visitKnownRecordImpl(CVSymbol &CVR, T &Record) {
     84 
     85     Record.RecordOffset =
     86         Delegate ? Delegate->getRecordOffset(Mapping->Reader) : 0;
     87     if (auto EC = Mapping->Mapping.visitKnownRecord(CVR, Record))
     88       return EC;
     89     return Error::success();
     90   }
     91 
     92   SymbolVisitorDelegate *Delegate;
     93   CodeViewContainer Container;
     94   std::unique_ptr<MappingInfo> Mapping;
     95 };
     96 }
     97 }
     98 
     99 #endif
    100