1 //===- DWARFDebugLine.h -----------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
10 #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
12 #include "llvm/ADT/Optional.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/DebugInfo/DIContext.h"
15 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
16 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
17 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
18 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
19 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
20 #include "llvm/Support/MD5.h"
21 #include "llvm/Support/Path.h"
32 class DWARFDebugLine
{
34 struct FileNameEntry
{
35 FileNameEntry() = default;
41 MD5::MD5Result Checksum
;
42 DWARFFormValue Source
;
45 /// Tracks which optional content types are present in a DWARF file name
47 struct ContentTypeTracker
{
48 ContentTypeTracker() = default;
50 /// Whether filename entries provide a modification timestamp.
51 bool HasModTime
= false;
52 /// Whether filename entries provide a file size.
53 bool HasLength
= false;
54 /// For v5, whether filename entries provide an MD5 checksum.
56 /// For v5, whether filename entries provide source text.
57 bool HasSource
= false;
59 /// Update tracked content types with \p ContentType.
60 void trackContentType(dwarf::LineNumberEntryFormat ContentType
);
66 /// The size in bytes of the statement information for this compilation unit
67 /// (not including the total_length field itself).
69 /// Version, address size (starting in v5), and DWARF32/64 format; these
70 /// parameters affect interpretation of forms (used in the directory and
71 /// file tables starting with v5).
72 dwarf::FormParams FormParams
;
73 /// The number of bytes following the prologue_length field to the beginning
74 /// of the first byte of the statement program itself.
75 uint64_t PrologueLength
;
76 /// In v5, size in bytes of a segment selector.
77 uint8_t SegSelectorSize
;
78 /// The size in bytes of the smallest target machine instruction. Statement
79 /// program opcodes that alter the address register first multiply their
80 /// operands by this value.
81 uint8_t MinInstLength
;
82 /// The maximum number of individual operations that may be encoded in an
84 uint8_t MaxOpsPerInst
;
85 /// The initial value of theis_stmtregister.
86 uint8_t DefaultIsStmt
;
87 /// This parameter affects the meaning of the special opcodes. See below.
89 /// This parameter affects the meaning of the special opcodes. See below.
91 /// The number assigned to the first special opcode.
93 /// This tracks which optional file format content types are present.
94 ContentTypeTracker ContentTypes
;
95 std::vector
<uint8_t> StandardOpcodeLengths
;
96 std::vector
<DWARFFormValue
> IncludeDirectories
;
97 std::vector
<FileNameEntry
> FileNames
;
99 const dwarf::FormParams
getFormParams() const { return FormParams
; }
100 uint16_t getVersion() const { return FormParams
.Version
; }
101 uint8_t getAddressSize() const { return FormParams
.AddrSize
; }
102 bool isDWARF64() const { return FormParams
.Format
== dwarf::DWARF64
; }
104 uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; }
106 uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; }
108 bool totalLengthIsValid() const;
110 /// Length of the prologue in bytes.
111 uint32_t getLength() const {
112 return PrologueLength
+ sizeofTotalLength() + sizeof(getVersion()) +
113 sizeofPrologueLength();
116 /// Length of the line table data in bytes (not including the prologue).
117 uint32_t getStatementTableLength() const {
118 return TotalLength
+ sizeofTotalLength() - getLength();
121 int32_t getMaxLineIncrementForSpecialOpcode() const {
122 return LineBase
+ (int8_t)LineRange
- 1;
125 /// Get DWARF-version aware access to the file name entry at the provided
127 const llvm::DWARFDebugLine::FileNameEntry
&
128 getFileNameEntry(uint64_t Index
) const;
130 bool hasFileAtIndex(uint64_t FileIndex
) const;
133 getFileNameByIndex(uint64_t FileIndex
, StringRef CompDir
,
134 DILineInfoSpecifier::FileLineInfoKind Kind
,
136 sys::path::Style Style
= sys::path::Style::native
) const;
139 void dump(raw_ostream
&OS
, DIDumpOptions DumpOptions
) const;
140 Error
parse(const DWARFDataExtractor
&DebugLineData
, uint64_t *OffsetPtr
,
141 const DWARFContext
&Ctx
, const DWARFUnit
*U
= nullptr);
144 /// Standard .debug_line state machine structure.
146 explicit Row(bool DefaultIsStmt
= false);
148 /// Called after a row is appended to the matrix.
150 void reset(bool DefaultIsStmt
);
151 void dump(raw_ostream
&OS
) const;
153 static void dumpTableHeader(raw_ostream
&OS
);
155 static bool orderByAddress(const Row
&LHS
, const Row
&RHS
) {
156 return std::tie(LHS
.Address
.SectionIndex
, LHS
.Address
.Address
) <
157 std::tie(RHS
.Address
.SectionIndex
, RHS
.Address
.Address
);
160 /// The program-counter value corresponding to a machine instruction
161 /// generated by the compiler and section index pointing to the section
162 /// containg this PC. If relocation information is present then section
163 /// index is the index of the section which contains above address.
164 /// Otherwise this is object::SectionedAddress::Undef value.
165 object::SectionedAddress Address
;
166 /// An unsigned integer indicating a source line number. Lines are numbered
167 /// beginning at 1. The compiler may emit the value 0 in cases where an
168 /// instruction cannot be attributed to any source line.
170 /// An unsigned integer indicating a column number within a source line.
171 /// Columns are numbered beginning at 1. The value 0 is reserved to indicate
172 /// that a statement begins at the 'left edge' of the line.
174 /// An unsigned integer indicating the identity of the source file
175 /// corresponding to a machine instruction.
177 /// An unsigned integer representing the DWARF path discriminator value
178 /// for this location.
179 uint32_t Discriminator
;
180 /// An unsigned integer whose value encodes the applicable instruction set
181 /// architecture for the current instruction.
183 /// A boolean indicating that the current instruction is the beginning of a
186 /// A boolean indicating that the current instruction is the
187 /// beginning of a basic block.
189 /// A boolean indicating that the current address is that of the
190 /// first byte after the end of a sequence of target machine
193 /// A boolean indicating that the current address is one (of possibly
194 /// many) where execution should be suspended for an entry breakpoint
197 /// A boolean indicating that the current address is one (of possibly
198 /// many) where execution should be suspended for an exit breakpoint
203 /// Represents a series of contiguous machine instructions. Line table for
204 /// each compilation unit may consist of multiple sequences, which are not
205 /// guaranteed to be in the order of ascending instruction address.
209 /// Sequence describes instructions at address range [LowPC, HighPC)
210 /// and is described by line table rows [FirstRowIndex, LastRowIndex).
213 /// If relocation information is present then this is the index of the
214 /// section which contains above addresses. Otherwise this is
215 /// object::SectionedAddress::Undef value.
216 uint64_t SectionIndex
;
217 unsigned FirstRowIndex
;
218 unsigned LastRowIndex
;
223 static bool orderByHighPC(const Sequence
&LHS
, const Sequence
&RHS
) {
224 return std::tie(LHS
.SectionIndex
, LHS
.HighPC
) <
225 std::tie(RHS
.SectionIndex
, RHS
.HighPC
);
228 bool isValid() const {
229 return !Empty
&& (LowPC
< HighPC
) && (FirstRowIndex
< LastRowIndex
);
232 bool containsPC(object::SectionedAddress PC
) const {
233 return SectionIndex
== PC
.SectionIndex
&&
234 (LowPC
<= PC
.Address
&& PC
.Address
< HighPC
);
241 /// Represents an invalid row
242 const uint32_t UnknownRowIndex
= UINT32_MAX
;
244 void appendRow(const DWARFDebugLine::Row
&R
) { Rows
.push_back(R
); }
246 void appendSequence(const DWARFDebugLine::Sequence
&S
) {
247 Sequences
.push_back(S
);
250 /// Returns the index of the row with file/line info for a given address,
251 /// or UnknownRowIndex if there is no such row.
252 uint32_t lookupAddress(object::SectionedAddress Address
) const;
254 bool lookupAddressRange(object::SectionedAddress Address
, uint64_t Size
,
255 std::vector
<uint32_t> &Result
) const;
257 bool hasFileAtIndex(uint64_t FileIndex
) const {
258 return Prologue
.hasFileAtIndex(FileIndex
);
261 /// Extracts filename by its index in filename table in prologue.
262 /// In Dwarf 4, the files are 1-indexed and the current compilation file
263 /// name is not represented in the list. In DWARF v5, the files are
264 /// 0-indexed and the primary source file has the index 0.
265 /// Returns true on success.
266 bool getFileNameByIndex(uint64_t FileIndex
, StringRef CompDir
,
267 DILineInfoSpecifier::FileLineInfoKind Kind
,
268 std::string
&Result
) const {
269 return Prologue
.getFileNameByIndex(FileIndex
, CompDir
, Kind
, Result
);
272 /// Fills the Result argument with the file and line information
273 /// corresponding to Address. Returns true on success.
274 bool getFileLineInfoForAddress(object::SectionedAddress Address
,
276 DILineInfoSpecifier::FileLineInfoKind Kind
,
277 DILineInfo
&Result
) const;
279 void dump(raw_ostream
&OS
, DIDumpOptions DumpOptions
) const;
282 /// Parse prologue and all rows.
284 DWARFDataExtractor
&DebugLineData
, uint64_t *OffsetPtr
,
285 const DWARFContext
&Ctx
, const DWARFUnit
*U
,
286 std::function
<void(Error
)> RecoverableErrorCallback
,
287 raw_ostream
*OS
= nullptr);
289 using RowVector
= std::vector
<Row
>;
290 using RowIter
= RowVector::const_iterator
;
291 using SequenceVector
= std::vector
<Sequence
>;
292 using SequenceIter
= SequenceVector::const_iterator
;
294 struct Prologue Prologue
;
296 SequenceVector Sequences
;
299 uint32_t findRowInSeq(const DWARFDebugLine::Sequence
&Seq
,
300 object::SectionedAddress Address
) const;
302 getSourceByIndex(uint64_t FileIndex
,
303 DILineInfoSpecifier::FileLineInfoKind Kind
) const;
305 uint32_t lookupAddressImpl(object::SectionedAddress Address
) const;
307 bool lookupAddressRangeImpl(object::SectionedAddress Address
, uint64_t Size
,
308 std::vector
<uint32_t> &Result
) const;
311 const LineTable
*getLineTable(uint64_t Offset
) const;
312 Expected
<const LineTable
*> getOrParseLineTable(
313 DWARFDataExtractor
&DebugLineData
, uint64_t Offset
,
314 const DWARFContext
&Ctx
, const DWARFUnit
*U
,
315 std::function
<void(Error
)> RecoverableErrorCallback
);
317 /// Helper to allow for parsing of an entire .debug_line section in sequence.
318 class SectionParser
{
320 using cu_range
= DWARFUnitVector::iterator_range
;
321 using tu_range
= DWARFUnitVector::iterator_range
;
322 using LineToUnitMap
= std::map
<uint64_t, DWARFUnit
*>;
324 SectionParser(DWARFDataExtractor
&Data
, const DWARFContext
&C
, cu_range CUs
,
327 /// Get the next line table from the section. Report any issues via the
330 /// \param RecoverableErrorCallback - any issues that don't prevent further
331 /// parsing of the table will be reported through this callback.
332 /// \param UnrecoverableErrorCallback - any issues that prevent further
333 /// parsing of the table will be reported through this callback.
334 /// \param OS - if not null, the parser will print information about the
335 /// table as it parses it.
338 function_ref
<void(Error
)> RecoverableErrorCallback
,
339 function_ref
<void(Error
)> UnrecoverableErrorCallback
,
340 raw_ostream
*OS
= nullptr);
342 /// Skip the current line table and go to the following line table (if
343 /// present) immediately.
345 /// \param ErrorCallback - report any prologue parsing issues via this
347 void skip(function_ref
<void(Error
)> ErrorCallback
);
349 /// Indicates if the parser has parsed as much as possible.
351 /// \note Certain problems with the line table structure might mean that
352 /// parsing stops before the end of the section is reached.
353 bool done() const { return Done
; }
355 /// Get the offset the parser has reached.
356 uint64_t getOffset() const { return Offset
; }
359 DWARFUnit
*prepareToParse(uint64_t Offset
);
360 void moveToNextTable(uint64_t OldOffset
, const Prologue
&P
);
362 LineToUnitMap LineToUnit
;
364 DWARFDataExtractor
&DebugLineData
;
365 const DWARFContext
&Context
;
371 struct ParsingState
{
372 ParsingState(struct LineTable
*LT
);
374 void resetRowAndSequence();
375 void appendRowToMatrix();
377 /// Line table we're currently parsing.
378 struct LineTable
*LineTable
;
380 struct Sequence Sequence
;
383 using LineTableMapTy
= std::map
<uint64_t, LineTable
>;
384 using LineTableIter
= LineTableMapTy::iterator
;
385 using LineTableConstIter
= LineTableMapTy::const_iterator
;
387 LineTableMapTy LineTableMap
;
390 } // end namespace llvm
392 #endif // LLVM_DEBUGINFO_DWARFDEBUGLINE_H