Coverage Report

Created: 2019-07-24 05:18

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