1//===- DebugLinesSubsection.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_MODULEDEBUGLINEFRAGMENT_H
11#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
12
13#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
14#include "llvm/DebugInfo/CodeView/Line.h"
15#include "llvm/Support/BinaryStreamArray.h"
16#include "llvm/Support/BinaryStreamReader.h"
17#include "llvm/Support/Error.h"
18
19namespace llvm {
20namespace codeview {
21
22class DebugChecksumsSubsection;
23class DebugStringTableSubsection;
24
25// Corresponds to the `CV_DebugSLinesHeader_t` structure.
26struct LineFragmentHeader {
27  support::ulittle32_t RelocOffset;  // Code offset of line contribution.
28  support::ulittle16_t RelocSegment; // Code segment of line contribution.
29  support::ulittle16_t Flags;        // See LineFlags enumeration.
30  support::ulittle32_t CodeSize;     // Code size of this line contribution.
31};
32
33// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
34struct LineBlockFragmentHeader {
35  support::ulittle32_t NameIndex; // Offset of FileChecksum entry in File
36                                  // checksums buffer.  The checksum entry then
37                                  // contains another offset into the string
38                                  // table of the actual name.
39  support::ulittle32_t NumLines;  // Number of lines
40  support::ulittle32_t BlockSize; // Code size of block, in bytes.
41  // The following two variable length arrays appear immediately after the
42  // header.  The structure definitions follow.
43  // LineNumberEntry   Lines[NumLines];
44  // ColumnNumberEntry Columns[NumLines];
45};
46
47// Corresponds to `CV_Line_t` structure
48struct LineNumberEntry {
49  support::ulittle32_t Offset; // Offset to start of code bytes for line number
50  support::ulittle32_t Flags;  // Start:24, End:7, IsStatement:1
51};
52
53// Corresponds to `CV_Column_t` structure
54struct ColumnNumberEntry {
55  support::ulittle16_t StartColumn;
56  support::ulittle16_t EndColumn;
57};
58
59struct LineColumnEntry {
60  support::ulittle32_t NameIndex;
61  FixedStreamArray<LineNumberEntry> LineNumbers;
62  FixedStreamArray<ColumnNumberEntry> Columns;
63};
64
65class LineColumnExtractor {
66public:
67  Error operator()(BinaryStreamRef Stream, uint32_t &Len,
68                   LineColumnEntry &Item);
69
70  const LineFragmentHeader *Header = nullptr;
71};
72
73class DebugLinesSubsectionRef final : public DebugSubsectionRef {
74  friend class LineColumnExtractor;
75  typedef VarStreamArray<LineColumnEntry, LineColumnExtractor> LineInfoArray;
76  typedef LineInfoArray::Iterator Iterator;
77
78public:
79  DebugLinesSubsectionRef();
80
81  static bool classof(const DebugSubsectionRef *S) {
82    return S->kind() == DebugSubsectionKind::Lines;
83  }
84
85  Error initialize(BinaryStreamReader Reader);
86
87  Iterator begin() const { return LinesAndColumns.begin(); }
88  Iterator end() const { return LinesAndColumns.end(); }
89
90  const LineFragmentHeader *header() const { return Header; }
91
92  bool hasColumnInfo() const;
93
94private:
95  const LineFragmentHeader *Header = nullptr;
96  LineInfoArray LinesAndColumns;
97};
98
99class DebugLinesSubsection final : public DebugSubsection {
100  struct Block {
101    Block(uint32_t ChecksumBufferOffset)
102        : ChecksumBufferOffset(ChecksumBufferOffset) {}
103
104    uint32_t ChecksumBufferOffset;
105    std::vector<LineNumberEntry> Lines;
106    std::vector<ColumnNumberEntry> Columns;
107  };
108
109public:
110  DebugLinesSubsection(DebugChecksumsSubsection &Checksums,
111                       DebugStringTableSubsection &Strings);
112
113  static bool classof(const DebugSubsection *S) {
114    return S->kind() == DebugSubsectionKind::Lines;
115  }
116
117  void createBlock(StringRef FileName);
118  void addLineInfo(uint32_t Offset, const LineInfo &Line);
119  void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line,
120                            uint32_t ColStart, uint32_t ColEnd);
121
122  uint32_t calculateSerializedSize() const override;
123  Error commit(BinaryStreamWriter &Writer) const override;
124
125  void setRelocationAddress(uint16_t Segment, uint32_t Offset);
126  void setCodeSize(uint32_t Size);
127  void setFlags(LineFlags Flags);
128
129  bool hasColumnInfo() const;
130
131private:
132  DebugChecksumsSubsection &Checksums;
133
134  uint32_t RelocOffset = 0;
135  uint16_t RelocSegment = 0;
136  uint32_t CodeSize = 0;
137  LineFlags Flags = LF_None;
138  std::vector<Block> Blocks;
139};
140}
141}
142
143#endif
144