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