Line data Source code
1 : //===- DWARFDebugLine.h -----------------------------------------*- C++ -*-===//
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 : #ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
11 : #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
12 :
13 : #include "llvm/ADT/Optional.h"
14 : #include "llvm/ADT/StringRef.h"
15 : #include "llvm/DebugInfo/DIContext.h"
16 : #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
17 : #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
18 : #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
19 : #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
20 : #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
21 : #include "llvm/Support/MD5.h"
22 : #include <cstdint>
23 : #include <map>
24 : #include <string>
25 : #include <vector>
26 :
27 : namespace llvm {
28 :
29 : class DWARFUnit;
30 : class raw_ostream;
31 :
32 32 : class DWARFDebugLine {
33 : public:
34 : struct FileNameEntry {
35 0 : FileNameEntry() = default;
36 :
37 : DWARFFormValue Name;
38 : uint64_t DirIdx = 0;
39 : uint64_t ModTime = 0;
40 : uint64_t Length = 0;
41 : MD5::MD5Result Checksum;
42 : DWARFFormValue Source;
43 : };
44 :
45 : /// Tracks which optional content types are present in a DWARF file name
46 : /// entry format.
47 : struct ContentTypeTracker {
48 1472 : ContentTypeTracker() = default;
49 :
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.
55 : bool HasMD5 = false;
56 : /// For v5, whether filename entries provide source text.
57 : bool HasSource = false;
58 :
59 : /// Update tracked content types with \p ContentType.
60 : void trackContentType(dwarf::LineNumberEntryFormat ContentType);
61 : };
62 :
63 : struct Prologue {
64 : Prologue();
65 :
66 : /// The size in bytes of the statement information for this compilation unit
67 : /// (not including the total_length field itself).
68 : uint64_t TotalLength;
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
83 : /// instruction.
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.
88 : int8_t LineBase;
89 : /// This parameter affects the meaning of the special opcodes. See below.
90 : uint8_t LineRange;
91 : /// The number assigned to the first special opcode.
92 : uint8_t OpcodeBase;
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;
98 :
99 : const dwarf::FormParams getFormParams() const { return FormParams; }
100 0 : uint16_t getVersion() const { return FormParams.Version; }
101 0 : uint8_t getAddressSize() const { return FormParams.AddrSize; }
102 0 : bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; }
103 :
104 1763 : uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; }
105 :
106 1409 : uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; }
107 :
108 : bool totalLengthIsValid() const;
109 :
110 : /// Length of the prologue in bytes.
111 : uint32_t getLength() const {
112 : return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) +
113 : sizeofPrologueLength();
114 : }
115 :
116 : /// Length of the line table data in bytes (not including the prologue).
117 : uint32_t getStatementTableLength() const {
118 : return TotalLength + sizeofTotalLength() - getLength();
119 : }
120 :
121 : int32_t getMaxLineIncrementForSpecialOpcode() const {
122 : return LineBase + (int8_t)LineRange - 1;
123 : }
124 :
125 : void clear();
126 : void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
127 : Error parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
128 : const DWARFContext &Ctx, const DWARFUnit *U = nullptr);
129 : };
130 :
131 : /// Standard .debug_line state machine structure.
132 : struct Row {
133 : explicit Row(bool DefaultIsStmt = false);
134 :
135 : /// Called after a row is appended to the matrix.
136 : void postAppend();
137 : void reset(bool DefaultIsStmt);
138 : void dump(raw_ostream &OS) const;
139 :
140 : static void dumpTableHeader(raw_ostream &OS);
141 :
142 3159 : static bool orderByAddress(const Row &LHS, const Row &RHS) {
143 3159 : return LHS.Address < RHS.Address;
144 : }
145 :
146 : /// The program-counter value corresponding to a machine instruction
147 : /// generated by the compiler.
148 : uint64_t Address;
149 : /// An unsigned integer indicating a source line number. Lines are numbered
150 : /// beginning at 1. The compiler may emit the value 0 in cases where an
151 : /// instruction cannot be attributed to any source line.
152 : uint32_t Line;
153 : /// An unsigned integer indicating a column number within a source line.
154 : /// Columns are numbered beginning at 1. The value 0 is reserved to indicate
155 : /// that a statement begins at the 'left edge' of the line.
156 : uint16_t Column;
157 : /// An unsigned integer indicating the identity of the source file
158 : /// corresponding to a machine instruction.
159 : uint16_t File;
160 : /// An unsigned integer representing the DWARF path discriminator value
161 : /// for this location.
162 : uint32_t Discriminator;
163 : /// An unsigned integer whose value encodes the applicable instruction set
164 : /// architecture for the current instruction.
165 : uint8_t Isa;
166 : /// A boolean indicating that the current instruction is the beginning of a
167 : /// statement.
168 : uint8_t IsStmt : 1,
169 : /// A boolean indicating that the current instruction is the
170 : /// beginning of a basic block.
171 : BasicBlock : 1,
172 : /// A boolean indicating that the current address is that of the
173 : /// first byte after the end of a sequence of target machine
174 : /// instructions.
175 : EndSequence : 1,
176 : /// A boolean indicating that the current address is one (of possibly
177 : /// many) where execution should be suspended for an entry breakpoint
178 : /// of a function.
179 : PrologueEnd : 1,
180 : /// A boolean indicating that the current address is one (of possibly
181 : /// many) where execution should be suspended for an exit breakpoint
182 : /// of a function.
183 : EpilogueBegin : 1;
184 : };
185 :
186 : /// Represents a series of contiguous machine instructions. Line table for
187 : /// each compilation unit may consist of multiple sequences, which are not
188 : /// guaranteed to be in the order of ascending instruction address.
189 : struct Sequence {
190 : Sequence();
191 :
192 : /// Sequence describes instructions at address range [LowPC, HighPC)
193 : /// and is described by line table rows [FirstRowIndex, LastRowIndex).
194 : uint64_t LowPC;
195 : uint64_t HighPC;
196 : unsigned FirstRowIndex;
197 : unsigned LastRowIndex;
198 : bool Empty;
199 :
200 : void reset();
201 :
202 1194 : static bool orderByLowPC(const Sequence &LHS, const Sequence &RHS) {
203 1194 : return LHS.LowPC < RHS.LowPC;
204 : }
205 :
206 : bool isValid() const {
207 1338 : return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex);
208 : }
209 :
210 800 : bool containsPC(uint64_t PC) const { return (LowPC <= PC && PC < HighPC); }
211 : };
212 :
213 : struct LineTable {
214 : LineTable();
215 :
216 : /// Represents an invalid row
217 : const uint32_t UnknownRowIndex = UINT32_MAX;
218 :
219 8094 : void appendRow(const DWARFDebugLine::Row &R) { Rows.push_back(R); }
220 :
221 : void appendSequence(const DWARFDebugLine::Sequence &S) {
222 1307 : Sequences.push_back(S);
223 : }
224 :
225 : /// Returns the index of the row with file/line info for a given address,
226 : /// or UnknownRowIndex if there is no such row.
227 : uint32_t lookupAddress(uint64_t Address) const;
228 :
229 : bool lookupAddressRange(uint64_t Address, uint64_t Size,
230 : std::vector<uint32_t> &Result) const;
231 :
232 : bool hasFileAtIndex(uint64_t FileIndex) const;
233 :
234 : /// Extracts filename by its index in filename table in prologue.
235 : /// Returns true on success.
236 : bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir,
237 : DILineInfoSpecifier::FileLineInfoKind Kind,
238 : std::string &Result) const;
239 :
240 : /// Fills the Result argument with the file and line information
241 : /// corresponding to Address. Returns true on success.
242 : bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir,
243 : DILineInfoSpecifier::FileLineInfoKind Kind,
244 : DILineInfo &Result) const;
245 :
246 : void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
247 : void clear();
248 :
249 : /// Parse prologue and all rows.
250 : Error parse(
251 : DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
252 : const DWARFContext &Ctx, const DWARFUnit *U,
253 : std::function<void(Error)> RecoverableErrorCallback,
254 : raw_ostream *OS = nullptr);
255 :
256 : using RowVector = std::vector<Row>;
257 : using RowIter = RowVector::const_iterator;
258 : using SequenceVector = std::vector<Sequence>;
259 : using SequenceIter = SequenceVector::const_iterator;
260 :
261 : struct Prologue Prologue;
262 : RowVector Rows;
263 : SequenceVector Sequences;
264 :
265 : private:
266 : uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq,
267 : uint64_t Address) const;
268 : Optional<StringRef>
269 : getSourceByIndex(uint64_t FileIndex,
270 : DILineInfoSpecifier::FileLineInfoKind Kind) const;
271 : };
272 :
273 : const LineTable *getLineTable(uint32_t Offset) const;
274 : Expected<const LineTable *> getOrParseLineTable(
275 : DWARFDataExtractor &DebugLineData, uint32_t Offset,
276 : const DWARFContext &Ctx, const DWARFUnit *U,
277 : std::function<void(Error)> RecoverableErrorCallback);
278 :
279 : /// Helper to allow for parsing of an entire .debug_line section in sequence.
280 241 : class SectionParser {
281 : public:
282 : using cu_range = DWARFUnitVector::iterator_range;
283 : using tu_range = DWARFUnitVector::iterator_range;
284 : using LineToUnitMap = std::map<uint64_t, DWARFUnit *>;
285 :
286 : SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, cu_range CUs,
287 : tu_range TUs);
288 :
289 : /// Get the next line table from the section. Report any issues via the
290 : /// callbacks.
291 : ///
292 : /// \param RecoverableErrorCallback - any issues that don't prevent further
293 : /// parsing of the table will be reported through this callback.
294 : /// \param UnrecoverableErrorCallback - any issues that prevent further
295 : /// parsing of the table will be reported through this callback.
296 : /// \param OS - if not null, the parser will print information about the
297 : /// table as it parses it.
298 : LineTable
299 : parseNext(
300 : function_ref<void(Error)> RecoverableErrorCallback,
301 : function_ref<void(Error)> UnrecoverableErrorCallback,
302 : raw_ostream *OS = nullptr);
303 :
304 : /// Skip the current line table and go to the following line table (if
305 : /// present) immediately.
306 : ///
307 : /// \param ErrorCallback - report any prologue parsing issues via this
308 : /// callback.
309 : void skip(function_ref<void(Error)> ErrorCallback);
310 :
311 : /// Indicates if the parser has parsed as much as possible.
312 : ///
313 : /// \note Certain problems with the line table structure might mean that
314 : /// parsing stops before the end of the section is reached.
315 0 : bool done() const { return Done; }
316 :
317 : /// Get the offset the parser has reached.
318 0 : uint32_t getOffset() const { return Offset; }
319 :
320 : private:
321 : DWARFUnit *prepareToParse(uint32_t Offset);
322 : void moveToNextTable(uint32_t OldOffset, const Prologue &P);
323 :
324 : LineToUnitMap LineToUnit;
325 :
326 : DWARFDataExtractor &DebugLineData;
327 : const DWARFContext &Context;
328 : uint32_t Offset = 0;
329 : bool Done = false;
330 : };
331 :
332 : private:
333 : struct ParsingState {
334 : ParsingState(struct LineTable *LT);
335 :
336 : void resetRowAndSequence();
337 : void appendRowToMatrix(uint32_t Offset);
338 :
339 : /// Line table we're currently parsing.
340 : struct LineTable *LineTable;
341 : /// The row number that starts at zero for the prologue, and increases for
342 : /// each row added to the matrix.
343 : unsigned RowNumber = 0;
344 : struct Row Row;
345 : struct Sequence Sequence;
346 : };
347 :
348 : using LineTableMapTy = std::map<uint32_t, LineTable>;
349 : using LineTableIter = LineTableMapTy::iterator;
350 : using LineTableConstIter = LineTableMapTy::const_iterator;
351 :
352 : LineTableMapTy LineTableMap;
353 : };
354 :
355 : } // end namespace llvm
356 :
357 : #endif // LLVM_DEBUGINFO_DWARFDEBUGLINE_H
|