• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 namespace llvm {
26 namespace codeview {
27 
28 class DebugChecksumsSubsection;
29 class DebugStringTableSubsection;
30 
31 // Corresponds to the `CV_DebugSLinesHeader_t` structure.
32 struct 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.
40 struct 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
54 struct 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
60 struct ColumnNumberEntry {
61   support::ulittle16_t StartColumn;
62   support::ulittle16_t EndColumn;
63 };
64 
65 struct LineColumnEntry {
66   support::ulittle32_t NameIndex;
67   FixedStreamArray<LineNumberEntry> LineNumbers;
68   FixedStreamArray<ColumnNumberEntry> Columns;
69 };
70 
71 class LineColumnExtractor {
72 public:
73   Error operator()(BinaryStreamRef Stream, uint32_t &Len,
74                    LineColumnEntry &Item);
75 
76   const LineFragmentHeader *Header = nullptr;
77 };
78 
79 class DebugLinesSubsectionRef final : public DebugSubsectionRef {
80   friend class LineColumnExtractor;
81 
82   using LineInfoArray = VarStreamArray<LineColumnEntry, LineColumnExtractor>;
83   using Iterator = LineInfoArray::Iterator;
84 
85 public:
86   DebugLinesSubsectionRef();
87 
classof(const DebugSubsectionRef * S)88   static bool classof(const DebugSubsectionRef *S) {
89     return S->kind() == DebugSubsectionKind::Lines;
90   }
91 
92   Error initialize(BinaryStreamReader Reader);
93 
begin()94   Iterator begin() const { return LinesAndColumns.begin(); }
end()95   Iterator end() const { return LinesAndColumns.end(); }
96 
header()97   const LineFragmentHeader *header() const { return Header; }
98 
99   bool hasColumnInfo() const;
100 
101 private:
102   const LineFragmentHeader *Header = nullptr;
103   LineInfoArray LinesAndColumns;
104 };
105 
106 class DebugLinesSubsection final : public DebugSubsection {
107   struct Block {
BlockBlock108     Block(uint32_t ChecksumBufferOffset)
109         : ChecksumBufferOffset(ChecksumBufferOffset) {}
110 
111     uint32_t ChecksumBufferOffset;
112     std::vector<LineNumberEntry> Lines;
113     std::vector<ColumnNumberEntry> Columns;
114   };
115 
116 public:
117   DebugLinesSubsection(DebugChecksumsSubsection &Checksums,
118                        DebugStringTableSubsection &Strings);
119 
classof(const DebugSubsection * S)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 
138 private:
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