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