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