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"
31 class DWARFDebugLine
{
33 struct FileNameEntry
{
34 FileNameEntry() = default;
40 MD5::MD5Result Checksum
;
41 DWARFFormValue Source
;
44 /// Tracks which optional content types are present in a DWARF file name
46 struct ContentTypeTracker
{
47 ContentTypeTracker() = default;
49 /// Whether filename entries provide a modification timestamp.
50 bool HasModTime
= false;
51 /// Whether filename entries provide a file size.
52 bool HasLength
= false;
53 /// For v5, whether filename entries provide an MD5 checksum.
55 /// For v5, whether filename entries provide source text.
56 bool HasSource
= false;
58 /// Update tracked content types with \p ContentType.
59 void trackContentType(dwarf::LineNumberEntryFormat ContentType
);
65 /// The size in bytes of the statement information for this compilation unit
66 /// (not including the total_length field itself).
68 /// Version, address size (starting in v5), and DWARF32/64 format; these
69 /// parameters affect interpretation of forms (used in the directory and
70 /// file tables starting with v5).
71 dwarf::FormParams FormParams
;
72 /// The number of bytes following the prologue_length field to the beginning
73 /// of the first byte of the statement program itself.
74 uint64_t PrologueLength
;
75 /// In v5, size in bytes of a segment selector.
76 uint8_t SegSelectorSize
;
77 /// The size in bytes of the smallest target machine instruction. Statement
78 /// program opcodes that alter the address register first multiply their
79 /// operands by this value.
80 uint8_t MinInstLength
;
81 /// The maximum number of individual operations that may be encoded in an
83 uint8_t MaxOpsPerInst
;
84 /// The initial value of theis_stmtregister.
85 uint8_t DefaultIsStmt
;
86 /// This parameter affects the meaning of the special opcodes. See below.
88 /// This parameter affects the meaning of the special opcodes. See below.
90 /// The number assigned to the first special opcode.
92 /// This tracks which optional file format content types are present.
93 ContentTypeTracker ContentTypes
;
94 std::vector
<uint8_t> StandardOpcodeLengths
;
95 std::vector
<DWARFFormValue
> IncludeDirectories
;
96 std::vector
<FileNameEntry
> FileNames
;
98 const dwarf::FormParams
getFormParams() const { return FormParams
; }
99 uint16_t getVersion() const { return FormParams
.Version
; }
100 uint8_t getAddressSize() const { return FormParams
.AddrSize
; }
101 bool isDWARF64() const { return FormParams
.Format
== dwarf::DWARF64
; }
103 uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; }
105 uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; }
107 bool totalLengthIsValid() const;
109 /// Length of the prologue in bytes.
110 uint32_t getLength() const {
111 return PrologueLength
+ sizeofTotalLength() + sizeof(getVersion()) +
112 sizeofPrologueLength();
115 /// Length of the line table data in bytes (not including the prologue).
116 uint32_t getStatementTableLength() const {
117 return TotalLength
+ sizeofTotalLength() - getLength();
120 int32_t getMaxLineIncrementForSpecialOpcode() const {
121 return LineBase
+ (int8_t)LineRange
- 1;
125 void dump(raw_ostream
&OS
, DIDumpOptions DumpOptions
) const;
126 Error
parse(const DWARFDataExtractor
&DebugLineData
, uint32_t *OffsetPtr
,
127 const DWARFContext
&Ctx
, const DWARFUnit
*U
= nullptr);
130 /// Standard .debug_line state machine structure.
132 explicit Row(bool DefaultIsStmt
= false);
134 /// Called after a row is appended to the matrix.
136 void reset(bool DefaultIsStmt
);
137 void dump(raw_ostream
&OS
) const;
139 static void dumpTableHeader(raw_ostream
&OS
);
141 static bool orderByAddress(const Row
&LHS
, const Row
&RHS
) {
142 return LHS
.Address
< RHS
.Address
;
145 /// The program-counter value corresponding to a machine instruction
146 /// generated by the compiler.
148 /// An unsigned integer indicating a source line number. Lines are numbered
149 /// beginning at 1. The compiler may emit the value 0 in cases where an
150 /// instruction cannot be attributed to any source line.
152 /// An unsigned integer indicating a column number within a source line.
153 /// Columns are numbered beginning at 1. The value 0 is reserved to indicate
154 /// that a statement begins at the 'left edge' of the line.
156 /// An unsigned integer indicating the identity of the source file
157 /// corresponding to a machine instruction.
159 /// An unsigned integer representing the DWARF path discriminator value
160 /// for this location.
161 uint32_t Discriminator
;
162 /// An unsigned integer whose value encodes the applicable instruction set
163 /// architecture for the current instruction.
165 /// A boolean indicating that the current instruction is the beginning of a
168 /// A boolean indicating that the current instruction is the
169 /// beginning of a basic block.
171 /// A boolean indicating that the current address is that of the
172 /// first byte after the end of a sequence of target machine
175 /// A boolean indicating that the current address is one (of possibly
176 /// many) where execution should be suspended for an entry breakpoint
179 /// A boolean indicating that the current address is one (of possibly
180 /// many) where execution should be suspended for an exit breakpoint
185 /// Represents a series of contiguous machine instructions. Line table for
186 /// each compilation unit may consist of multiple sequences, which are not
187 /// guaranteed to be in the order of ascending instruction address.
191 /// Sequence describes instructions at address range [LowPC, HighPC)
192 /// and is described by line table rows [FirstRowIndex, LastRowIndex).
195 unsigned FirstRowIndex
;
196 unsigned LastRowIndex
;
201 static bool orderByLowPC(const Sequence
&LHS
, const Sequence
&RHS
) {
202 return LHS
.LowPC
< RHS
.LowPC
;
205 bool isValid() const {
206 return !Empty
&& (LowPC
< HighPC
) && (FirstRowIndex
< LastRowIndex
);
209 bool containsPC(uint64_t PC
) const { return (LowPC
<= PC
&& PC
< HighPC
); }
215 /// Represents an invalid row
216 const uint32_t UnknownRowIndex
= UINT32_MAX
;
218 void appendRow(const DWARFDebugLine::Row
&R
) { Rows
.push_back(R
); }
220 void appendSequence(const DWARFDebugLine::Sequence
&S
) {
221 Sequences
.push_back(S
);
224 /// Returns the index of the row with file/line info for a given address,
225 /// or UnknownRowIndex if there is no such row.
226 uint32_t lookupAddress(uint64_t Address
) const;
228 bool lookupAddressRange(uint64_t Address
, uint64_t Size
,
229 std::vector
<uint32_t> &Result
) const;
231 bool hasFileAtIndex(uint64_t FileIndex
) const;
233 /// Extracts filename by its index in filename table in prologue.
234 /// Returns true on success.
235 bool getFileNameByIndex(uint64_t FileIndex
, const char *CompDir
,
236 DILineInfoSpecifier::FileLineInfoKind Kind
,
237 std::string
&Result
) const;
239 /// Fills the Result argument with the file and line information
240 /// corresponding to Address. Returns true on success.
241 bool getFileLineInfoForAddress(uint64_t Address
, const char *CompDir
,
242 DILineInfoSpecifier::FileLineInfoKind Kind
,
243 DILineInfo
&Result
) const;
245 void dump(raw_ostream
&OS
, DIDumpOptions DumpOptions
) const;
248 /// Parse prologue and all rows.
250 DWARFDataExtractor
&DebugLineData
, uint32_t *OffsetPtr
,
251 const DWARFContext
&Ctx
, const DWARFUnit
*U
,
252 std::function
<void(Error
)> RecoverableErrorCallback
,
253 raw_ostream
*OS
= nullptr);
255 using RowVector
= std::vector
<Row
>;
256 using RowIter
= RowVector::const_iterator
;
257 using SequenceVector
= std::vector
<Sequence
>;
258 using SequenceIter
= SequenceVector::const_iterator
;
260 struct Prologue Prologue
;
262 SequenceVector Sequences
;
265 uint32_t findRowInSeq(const DWARFDebugLine::Sequence
&Seq
,
266 uint64_t Address
) const;
268 getSourceByIndex(uint64_t FileIndex
,
269 DILineInfoSpecifier::FileLineInfoKind Kind
) const;
272 const LineTable
*getLineTable(uint32_t Offset
) const;
273 Expected
<const LineTable
*> getOrParseLineTable(
274 DWARFDataExtractor
&DebugLineData
, uint32_t Offset
,
275 const DWARFContext
&Ctx
, const DWARFUnit
*U
,
276 std::function
<void(Error
)> RecoverableErrorCallback
);
278 /// Helper to allow for parsing of an entire .debug_line section in sequence.
279 class SectionParser
{
281 using cu_range
= DWARFUnitVector::iterator_range
;
282 using tu_range
= DWARFUnitVector::iterator_range
;
283 using LineToUnitMap
= std::map
<uint64_t, DWARFUnit
*>;
285 SectionParser(DWARFDataExtractor
&Data
, const DWARFContext
&C
, cu_range CUs
,
288 /// Get the next line table from the section. Report any issues via the
291 /// \param RecoverableErrorCallback - any issues that don't prevent further
292 /// parsing of the table will be reported through this callback.
293 /// \param UnrecoverableErrorCallback - any issues that prevent further
294 /// parsing of the table will be reported through this callback.
295 /// \param OS - if not null, the parser will print information about the
296 /// table as it parses it.
299 function_ref
<void(Error
)> RecoverableErrorCallback
,
300 function_ref
<void(Error
)> UnrecoverableErrorCallback
,
301 raw_ostream
*OS
= nullptr);
303 /// Skip the current line table and go to the following line table (if
304 /// present) immediately.
306 /// \param ErrorCallback - report any prologue parsing issues via this
308 void skip(function_ref
<void(Error
)> ErrorCallback
);
310 /// Indicates if the parser has parsed as much as possible.
312 /// \note Certain problems with the line table structure might mean that
313 /// parsing stops before the end of the section is reached.
314 bool done() const { return Done
; }
316 /// Get the offset the parser has reached.
317 uint32_t getOffset() const { return Offset
; }
320 DWARFUnit
*prepareToParse(uint32_t Offset
);
321 void moveToNextTable(uint32_t OldOffset
, const Prologue
&P
);
323 LineToUnitMap LineToUnit
;
325 DWARFDataExtractor
&DebugLineData
;
326 const DWARFContext
&Context
;
332 struct ParsingState
{
333 ParsingState(struct LineTable
*LT
);
335 void resetRowAndSequence();
336 void appendRowToMatrix(uint32_t Offset
);
338 /// Line table we're currently parsing.
339 struct LineTable
*LineTable
;
340 /// The row number that starts at zero for the prologue, and increases for
341 /// each row added to the matrix.
342 unsigned RowNumber
= 0;
344 struct Sequence Sequence
;
347 using LineTableMapTy
= std::map
<uint32_t, LineTable
>;
348 using LineTableIter
= LineTableMapTy::iterator
;
349 using LineTableConstIter
= LineTableMapTy::const_iterator
;
351 LineTableMapTy LineTableMap
;
354 } // end namespace llvm
356 #endif // LLVM_DEBUGINFO_DWARFDEBUGLINE_H