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