Line data Source code
1 : //===- ModuleDebugLineFragment.cpp -------------------------------*- 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 : #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
11 :
12 : #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13 : #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
14 : #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
15 : #include "llvm/DebugInfo/CodeView/StringTable.h"
16 :
17 : using namespace llvm;
18 : using namespace llvm::codeview;
19 :
20 135 : Error LineColumnExtractor::extract(BinaryStreamRef Stream, uint32_t &Len,
21 : LineColumnEntry &Item,
22 : const LineFragmentHeader *Header) {
23 : using namespace codeview;
24 : const LineBlockFragmentHeader *BlockHeader;
25 405 : BinaryStreamReader Reader(Stream);
26 405 : if (auto EC = Reader.readObject(BlockHeader))
27 0 : return EC;
28 270 : bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns);
29 : uint32_t LineInfoSize =
30 135 : BlockHeader->NumLines *
31 270 : (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0));
32 270 : if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader))
33 : return make_error<CodeViewError>(cv_error_code::corrupt_record,
34 0 : "Invalid line block record size");
35 270 : uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader);
36 135 : if (LineInfoSize > Size)
37 : return make_error<CodeViewError>(cv_error_code::corrupt_record,
38 0 : "Invalid line block record size");
39 : // The value recorded in BlockHeader->BlockSize includes the size of
40 : // LineBlockFragmentHeader.
41 270 : Len = BlockHeader->BlockSize;
42 135 : Item.NameIndex = BlockHeader->NameIndex;
43 540 : if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines))
44 0 : return EC;
45 135 : if (HasColumn) {
46 276 : if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines))
47 0 : return EC;
48 : }
49 405 : return Error::success();
50 : }
51 :
52 118 : ModuleDebugLineFragmentRef::ModuleDebugLineFragmentRef()
53 354 : : ModuleDebugFragmentRef(ModuleDebugFragmentKind::Lines) {}
54 :
55 118 : Error ModuleDebugLineFragmentRef::initialize(BinaryStreamReader Reader) {
56 354 : if (auto EC = Reader.readObject(Header))
57 0 : return EC;
58 :
59 118 : if (auto EC =
60 354 : Reader.readArray(LinesAndColumns, Reader.bytesRemaining(), Header))
61 0 : return EC;
62 :
63 354 : return Error::success();
64 : }
65 :
66 372 : bool ModuleDebugLineFragmentRef::hasColumnInfo() const {
67 744 : return !!(Header->Flags & LF_HaveColumns);
68 : }
69 :
70 1 : ModuleDebugLineFragment::ModuleDebugLineFragment(
71 1 : ModuleDebugFileChecksumFragment &Checksums, StringTable &Strings)
72 : : ModuleDebugFragment(ModuleDebugFragmentKind::Lines),
73 3 : Checksums(Checksums) {}
74 :
75 1 : void ModuleDebugLineFragment::createBlock(StringRef FileName) {
76 1 : uint32_t Offset = Checksums.mapChecksumOffset(FileName);
77 :
78 1 : Blocks.emplace_back(Offset);
79 1 : }
80 :
81 3 : void ModuleDebugLineFragment::addLineInfo(uint32_t Offset,
82 : const LineInfo &Line) {
83 6 : Block &B = Blocks.back();
84 3 : LineNumberEntry LNE;
85 6 : LNE.Flags = Line.getRawData();
86 3 : LNE.Offset = Offset;
87 3 : B.Lines.push_back(LNE);
88 3 : }
89 :
90 0 : void ModuleDebugLineFragment::addLineAndColumnInfo(uint32_t Offset,
91 : const LineInfo &Line,
92 : uint32_t ColStart,
93 : uint32_t ColEnd) {
94 0 : Block &B = Blocks.back();
95 : assert(B.Lines.size() == B.Columns.size());
96 :
97 0 : addLineInfo(Offset, Line);
98 0 : ColumnNumberEntry CNE;
99 0 : CNE.StartColumn = ColStart;
100 0 : CNE.EndColumn = ColEnd;
101 0 : B.Columns.push_back(CNE);
102 0 : }
103 :
104 1 : Error ModuleDebugLineFragment::commit(BinaryStreamWriter &Writer) {
105 1 : LineFragmentHeader Header;
106 2 : Header.CodeSize = CodeSize;
107 2 : Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0;
108 2 : Header.RelocOffset = RelocOffset;
109 2 : Header.RelocSegment = RelocSegment;
110 :
111 3 : if (auto EC = Writer.writeObject(Header))
112 0 : return EC;
113 :
114 5 : for (const auto &B : Blocks) {
115 1 : LineBlockFragmentHeader BlockHeader;
116 : assert(B.Lines.size() == B.Columns.size() || B.Columns.empty());
117 :
118 3 : BlockHeader.NumLines = B.Lines.size();
119 1 : BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader);
120 2 : BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry);
121 1 : if (hasColumnInfo())
122 0 : BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry);
123 2 : BlockHeader.NameIndex = B.ChecksumBufferOffset;
124 3 : if (auto EC = Writer.writeObject(BlockHeader))
125 0 : return EC;
126 :
127 4 : if (auto EC = Writer.writeArray(makeArrayRef(B.Lines)))
128 0 : return EC;
129 :
130 1 : if (hasColumnInfo()) {
131 0 : if (auto EC = Writer.writeArray(makeArrayRef(B.Columns)))
132 0 : return EC;
133 : }
134 : }
135 3 : return Error::success();
136 : }
137 :
138 3 : uint32_t ModuleDebugLineFragment::calculateSerializedLength() {
139 3 : uint32_t Size = sizeof(LineFragmentHeader);
140 15 : for (const auto &B : Blocks) {
141 3 : Size += sizeof(LineBlockFragmentHeader);
142 6 : Size += B.Lines.size() * sizeof(LineNumberEntry);
143 3 : if (hasColumnInfo())
144 0 : Size += B.Columns.size() * sizeof(ColumnNumberEntry);
145 : }
146 3 : return Size;
147 : }
148 :
149 1 : void ModuleDebugLineFragment::setRelocationAddress(uint16_t Segment,
150 : uint16_t Offset) {
151 1 : RelocOffset = Offset;
152 1 : RelocSegment = Segment;
153 1 : }
154 :
155 1 : void ModuleDebugLineFragment::setCodeSize(uint32_t Size) { CodeSize = Size; }
156 :
157 1 : void ModuleDebugLineFragment::setFlags(LineFlags Flags) { this->Flags = Flags; }
158 :
159 7 : bool ModuleDebugLineFragment::hasColumnInfo() const {
160 7 : return Flags & LF_HaveColumns;
161 : }
|