Home | History | Annotate | Download | only in CodeView
      1 //===- ModuleSubstreamVisitor.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_MODULESUBSTREAMVISITOR_H
     11 #define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
     12 
     13 #include "llvm/ADT/ArrayRef.h"
     14 #include "llvm/DebugInfo/CodeView/CodeView.h"
     15 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
     16 #include "llvm/DebugInfo/CodeView/Line.h"
     17 #include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
     18 #include "llvm/Support/BinaryStreamArray.h"
     19 #include "llvm/Support/BinaryStreamReader.h"
     20 #include "llvm/Support/BinaryStreamRef.h"
     21 #include "llvm/Support/Endian.h"
     22 #include "llvm/Support/Error.h"
     23 #include <cstdint>
     24 
     25 namespace llvm {
     26 
     27 namespace codeview {
     28 
     29 struct LineColumnEntry {
     30   support::ulittle32_t NameIndex;
     31   FixedStreamArray<LineNumberEntry> LineNumbers;
     32   FixedStreamArray<ColumnNumberEntry> Columns;
     33 };
     34 
     35 struct FileChecksumEntry {
     36   uint32_t FileNameOffset;    // Byte offset of filename in global stringtable.
     37   FileChecksumKind Kind;      // The type of checksum.
     38   ArrayRef<uint8_t> Checksum; // The bytes of the checksum.
     39 };
     40 
     41 typedef VarStreamArray<LineColumnEntry> LineInfoArray;
     42 typedef VarStreamArray<FileChecksumEntry> FileChecksumArray;
     43 
     44 class IModuleSubstreamVisitor {
     45 public:
     46   virtual ~IModuleSubstreamVisitor() = default;
     47 
     48   virtual Error visitUnknown(ModuleSubstreamKind Kind,
     49                              BinaryStreamRef Data) = 0;
     50   virtual Error visitSymbols(BinaryStreamRef Data);
     51   virtual Error visitLines(BinaryStreamRef Data,
     52                            const LineSubstreamHeader *Header,
     53                            const LineInfoArray &Lines);
     54   virtual Error visitStringTable(BinaryStreamRef Data);
     55   virtual Error visitFileChecksums(BinaryStreamRef Data,
     56                                    const FileChecksumArray &Checksums);
     57   virtual Error visitFrameData(BinaryStreamRef Data);
     58   virtual Error visitInlineeLines(BinaryStreamRef Data);
     59   virtual Error visitCrossScopeImports(BinaryStreamRef Data);
     60   virtual Error visitCrossScopeExports(BinaryStreamRef Data);
     61   virtual Error visitILLines(BinaryStreamRef Data);
     62   virtual Error visitFuncMDTokenMap(BinaryStreamRef Data);
     63   virtual Error visitTypeMDTokenMap(BinaryStreamRef Data);
     64   virtual Error visitMergedAssemblyInput(BinaryStreamRef Data);
     65   virtual Error visitCoffSymbolRVA(BinaryStreamRef Data);
     66 };
     67 
     68 Error visitModuleSubstream(const ModuleSubstream &R,
     69                            IModuleSubstreamVisitor &V);
     70 } // end namespace codeview
     71 
     72 template <> class VarStreamArrayExtractor<codeview::LineColumnEntry> {
     73 public:
     74   VarStreamArrayExtractor(const codeview::LineSubstreamHeader *Header)
     75       : Header(Header) {}
     76 
     77   Error operator()(BinaryStreamRef Stream, uint32_t &Len,
     78                    codeview::LineColumnEntry &Item) const {
     79     using namespace codeview;
     80     const LineFileBlockHeader *BlockHeader;
     81     BinaryStreamReader Reader(Stream);
     82     if (auto EC = Reader.readObject(BlockHeader))
     83       return EC;
     84     bool HasColumn = Header->Flags & LineFlags::HaveColumns;
     85     uint32_t LineInfoSize =
     86         BlockHeader->NumLines *
     87         (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0));
     88     if (BlockHeader->BlockSize < sizeof(LineFileBlockHeader))
     89       return make_error<CodeViewError>(cv_error_code::corrupt_record,
     90                                        "Invalid line block record size");
     91     uint32_t Size = BlockHeader->BlockSize - sizeof(LineFileBlockHeader);
     92     if (LineInfoSize > Size)
     93       return make_error<CodeViewError>(cv_error_code::corrupt_record,
     94                                        "Invalid line block record size");
     95     // The value recorded in BlockHeader->BlockSize includes the size of
     96     // LineFileBlockHeader.
     97     Len = BlockHeader->BlockSize;
     98     Item.NameIndex = BlockHeader->NameIndex;
     99     if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines))
    100       return EC;
    101     if (HasColumn) {
    102       if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines))
    103         return EC;
    104     }
    105     return Error::success();
    106   }
    107 
    108 private:
    109   const codeview::LineSubstreamHeader *Header;
    110 };
    111 
    112 template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> {
    113 public:
    114   Error operator()(BinaryStreamRef Stream, uint32_t &Len,
    115                    codeview::FileChecksumEntry &Item) const {
    116     using namespace codeview;
    117     const FileChecksum *Header;
    118     BinaryStreamReader Reader(Stream);
    119     if (auto EC = Reader.readObject(Header))
    120       return EC;
    121     Item.FileNameOffset = Header->FileNameOffset;
    122     Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind);
    123     if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize))
    124       return EC;
    125     Len = sizeof(FileChecksum) + Header->ChecksumSize;
    126     return Error::success();
    127   }
    128 };
    129 
    130 } // end namespace llvm
    131 
    132 #endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
    133