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