1 //===- DebugLinesSubsection.cpp -------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
22 using namespace llvm::codeview
;
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
))
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
))
48 if (auto EC
= Reader
.readArray(Item
.Columns
, BlockHeader
->NumLines
))
51 return Error::success();
54 DebugLinesSubsectionRef::DebugLinesSubsectionRef()
55 : DebugSubsectionRef(DebugSubsectionKind::Lines
) {}
57 Error
DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader
) {
58 if (auto EC
= Reader
.readObject(Header
))
61 LinesAndColumns
.getExtractor().Header
= Header
;
62 if (auto EC
= Reader
.readArray(LinesAndColumns
, Reader
.bytesRemaining()))
65 return Error::success();
68 bool DebugLinesSubsectionRef::hasColumnInfo() const {
69 return !!(Header
->Flags
& LF_HaveColumns
);
72 DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection
&Checksums
,
73 DebugStringTableSubsection
&Strings
)
74 : DebugSubsection(DebugSubsectionKind::Lines
), Checksums(Checksums
) {}
76 void DebugLinesSubsection::createBlock(StringRef FileName
) {
77 uint32_t Offset
= Checksums
.mapChecksumOffset(FileName
);
79 Blocks
.emplace_back(Offset
);
82 void DebugLinesSubsection::addLineInfo(uint32_t Offset
, const LineInfo
&Line
) {
83 Block
&B
= Blocks
.back();
85 LNE
.Flags
= Line
.getRawData();
87 B
.Lines
.push_back(LNE
);
90 void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset
,
94 Block
&B
= Blocks
.back();
95 assert(B
.Lines
.size() == B
.Columns
.size());
97 addLineInfo(Offset
, Line
);
98 ColumnNumberEntry CNE
;
99 CNE
.StartColumn
= ColStart
;
100 CNE
.EndColumn
= ColEnd
;
101 B
.Columns
.push_back(CNE
);
104 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
;
111 if (auto EC
= Writer
.writeObject(Header
))
114 for (const auto &B
: Blocks
) {
115 LineBlockFragmentHeader BlockHeader
;
116 assert(B
.Lines
.size() == B
.Columns
.size() || B
.Columns
.empty());
118 BlockHeader
.NumLines
= B
.Lines
.size();
119 BlockHeader
.BlockSize
= sizeof(LineBlockFragmentHeader
);
120 BlockHeader
.BlockSize
+= BlockHeader
.NumLines
* sizeof(LineNumberEntry
);
122 BlockHeader
.BlockSize
+= BlockHeader
.NumLines
* sizeof(ColumnNumberEntry
);
123 BlockHeader
.NameIndex
= B
.ChecksumBufferOffset
;
124 if (auto EC
= Writer
.writeObject(BlockHeader
))
127 if (auto EC
= Writer
.writeArray(makeArrayRef(B
.Lines
)))
130 if (hasColumnInfo()) {
131 if (auto EC
= Writer
.writeArray(makeArrayRef(B
.Columns
)))
135 return Error::success();
138 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
);
144 Size
+= B
.Columns
.size() * sizeof(ColumnNumberEntry
);
149 void DebugLinesSubsection::setRelocationAddress(uint16_t Segment
,
151 RelocOffset
= Offset
;
152 RelocSegment
= Segment
;
155 void DebugLinesSubsection::setCodeSize(uint32_t Size
) { CodeSize
= Size
; }
157 void DebugLinesSubsection::setFlags(LineFlags Flags
) { this->Flags
= Flags
; }
159 bool DebugLinesSubsection::hasColumnInfo() const {
160 return Flags
& LF_HaveColumns
;