Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
Line
Count
Source (jump to first uncovered line)
1
//===- DWARFVerifier.h ----------------------------------------------------===//
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_DWARF_DWARFVERIFIER_H
11
#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
12
13
#include "llvm/DebugInfo/DIContext.h"
14
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
15
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
16
17
#include <cstdint>
18
#include <map>
19
#include <set>
20
21
namespace llvm {
22
class raw_ostream;
23
struct DWARFAttribute;
24
class DWARFContext;
25
class DWARFDie;
26
class DWARFUnit;
27
class DWARFAcceleratorTable;
28
class DWARFDataExtractor;
29
class DWARFDebugAbbrev;
30
class DataExtractor;
31
struct DWARFSection;
32
33
/// A class that verifies DWARF debug information given a DWARF Context.
34
class DWARFVerifier {
35
public:
36
  /// A class that keeps the address range information for a single DIE.
37
  struct DieRangeInfo {
38
    DWARFDie Die;
39
40
    /// Sorted DWARFAddressRanges.
41
    std::vector<DWARFAddressRange> Ranges;
42
43
    /// Sorted DWARFAddressRangeInfo.
44
    std::set<DieRangeInfo> Children;
45
46
27
    DieRangeInfo() = default;
47
158
    DieRangeInfo(DWARFDie Die) : Die(Die) {}
48
49
    /// Used for unit testing.
50
    DieRangeInfo(std::vector<DWARFAddressRange> Ranges)
51
0
        : Ranges(std::move(Ranges)) {}
52
53
    typedef std::vector<DWARFAddressRange>::const_iterator
54
        address_range_iterator;
55
    typedef std::set<DieRangeInfo>::const_iterator die_range_info_iterator;
56
57
    /// Inserts the address range. If the range overlaps with an existing
58
    /// range, the range is *not* added and an iterator to the overlapping
59
    /// range is returned.
60
    ///
61
    /// This is used for finding overlapping ranges within the same DIE.
62
    address_range_iterator insert(const DWARFAddressRange &R);
63
64
    /// Finds an address range in the sorted vector of ranges.
65
287
    address_range_iterator findRange(const DWARFAddressRange &R) const {
66
287
      auto Begin = Ranges.begin();
67
287
      auto End = Ranges.end();
68
287
      auto Iter = std::upper_bound(Begin, End, R);
69
287
      if (Iter != Begin)
70
269
        --Iter;
71
287
      return Iter;
72
287
    }
73
74
    /// Inserts the address range info. If any of its ranges overlaps with a
75
    /// range in an existing range info, the range info is *not* added and an
76
    /// iterator to the overlapping range info.
77
    ///
78
    /// This is used for finding overlapping children of the same DIE.
79
    die_range_info_iterator insert(const DieRangeInfo &RI);
80
81
    /// Return true if ranges in this object contains all ranges within RHS.
82
    bool contains(const DieRangeInfo &RHS) const;
83
84
    /// Return true if any range in this object intersects with any range in
85
    /// RHS.
86
    bool intersects(const DieRangeInfo &RHS) const;
87
  };
88
89
private:
90
  raw_ostream &OS;
91
  DWARFContext &DCtx;
92
  DIDumpOptions DumpOpts;
93
  /// A map that tracks all references (converted absolute references) so we
94
  /// can verify each reference points to a valid DIE and not an offset that
95
  /// lies between to valid DIEs.
96
  std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets;
97
  uint32_t NumDebugLineErrors = 0;
98
99
  /// Verifies the abbreviations section.
100
  ///
101
  /// This function currently checks that:
102
  /// --No abbreviation declaration has more than one attributes with the same
103
  /// name.
104
  ///
105
  /// \param Abbrev Pointer to the abbreviations section we are verifying
106
  /// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo.
107
  ///
108
  /// \returns The number of errors that occured during verification.
109
  unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev);
110
111
  /// Verifies the header of a unit in the .debug_info section.
112
  ///
113
  /// This function currently checks for:
114
  /// - Unit is in 32-bit DWARF format. The function can be modified to
115
  /// support 64-bit format.
116
  /// - The DWARF version is valid
117
  /// - The unit type is valid (if unit is in version >=5)
118
  /// - The unit doesn't extend beyond .debug_info section
119
  /// - The address size is valid
120
  /// - The offset in the .debug_abbrev section is valid
121
  ///
122
  /// \param DebugInfoData The .debug_info section data
123
  /// \param Offset A reference to the offset start of the unit. The offset will
124
  /// be updated to point to the next unit in .debug_info
125
  /// \param UnitIndex The index of the unit to be verified
126
  /// \param UnitType A reference to the type of the unit
127
  /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is
128
  /// in 64-bit format.
129
  ///
130
  /// \returns true if the header is verified successfully, false otherwise.
131
  bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
132
                        uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType,
133
                        bool &isUnitDWARF64);
134
135
136
  bool verifyUnitContents(DWARFUnit Unit);
137
138
  /// Verify that all Die ranges are valid.
139
  ///
140
  /// This function currently checks for:
141
  /// - cases in which lowPC >= highPC
142
  ///
143
  /// \returns Number of errors that occured during verification.
144
  unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI);
145
146
  /// Verifies the attribute's DWARF attribute and its value.
147
  ///
148
  /// This function currently checks for:
149
  /// - DW_AT_ranges values is a valid .debug_ranges offset
150
  /// - DW_AT_stmt_list is a valid .debug_line offset
151
  ///
152
  /// \param Die          The DWARF DIE that owns the attribute value
153
  /// \param AttrValue    The DWARF attribute value to check
154
  ///
155
  /// \returns NumErrors The number of errors occured during verification of
156
  /// attributes' values in a .debug_info section unit
157
  unsigned verifyDebugInfoAttribute(const DWARFDie &Die,
158
                                    DWARFAttribute &AttrValue);
159
160
  /// Verifies the attribute's DWARF form.
161
  ///
162
  /// This function currently checks for:
163
  /// - All DW_FORM_ref values that are CU relative have valid CU offsets
164
  /// - All DW_FORM_ref_addr values have valid .debug_info offsets
165
  /// - All DW_FORM_strp values have valid .debug_str offsets
166
  ///
167
  /// \param Die          The DWARF DIE that owns the attribute value
168
  /// \param AttrValue    The DWARF attribute value to check
169
  ///
170
  /// \returns NumErrors The number of errors occured during verification of
171
  /// attributes' forms in a .debug_info section unit
172
  unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue);
173
174
  /// Verifies the all valid references that were found when iterating through
175
  /// all of the DIE attributes.
176
  ///
177
  /// This function will verify that all references point to DIEs whose DIE
178
  /// offset matches. This helps to ensure if a DWARF link phase moved things
179
  /// around, that it doesn't create invalid references by failing to relocate
180
  /// CU relative and absolute references.
181
  ///
182
  /// \returns NumErrors The number of errors occured during verification of
183
  /// references for the .debug_info section
184
  unsigned verifyDebugInfoReferences();
185
186
  /// Verify the the DW_AT_stmt_list encoding and value and ensure that no
187
  /// compile units that have the same DW_AT_stmt_list value.
188
  void verifyDebugLineStmtOffsets();
189
190
  /// Verify that all of the rows in the line table are valid.
191
  ///
192
  /// This function currently checks for:
193
  /// - addresses within a sequence that decrease in value
194
  /// - invalid file indexes
195
  void verifyDebugLineRows();
196
197
  /// Verify that an Apple-style accelerator table is valid.
198
  ///
199
  /// This function currently checks that:
200
  /// - The fixed part of the header fits in the section
201
  /// - The size of the section is as large as what the header describes
202
  /// - There is at least one atom
203
  /// - The form for each atom is valid
204
  /// - The tag for each DIE in the table is valid
205
  /// - The buckets have a valid index, or they are empty
206
  /// - Each hashdata offset is valid
207
  /// - Each DIE is valid
208
  ///
209
  /// \param AccelSection pointer to the section containing the acceleration table
210
  /// \param StrData pointer to the string section
211
  /// \param SectionName the name of the table we're verifying
212
  ///
213
  /// \returns The number of errors occured during verification
214
  unsigned verifyAccelTable(const DWARFSection *AccelSection,
215
                            DataExtractor *StrData, const char *SectionName);
216
217
public:
218
  DWARFVerifier(raw_ostream &S, DWARFContext &D,
219
                DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE())
220
29
      : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)) {}
221
  /// Verify the information in any of the following sections, if available:
222
  /// .debug_abbrev, debug_abbrev.dwo
223
  ///
224
  /// Any errors are reported to the stream that was this object was
225
  /// constructed with.
226
  ///
227
  /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully,
228
  /// false otherwise.
229
  bool handleDebugAbbrev();
230
231
  /// Verify the information in the .debug_info section.
232
  ///
233
  /// Any errors are reported to the stream that was this object was
234
  /// constructed with.
235
  ///
236
  /// \returns true if the .debug_info verifies successfully, false otherwise.
237
  bool handleDebugInfo();
238
239
  /// Verify the information in the .debug_line section.
240
  ///
241
  /// Any errors are reported to the stream that was this object was
242
  /// constructed with.
243
  ///
244
  /// \returns true if the .debug_line verifies successfully, false otherwise.
245
  bool handleDebugLine();
246
247
  /// Verify the information in accelerator tables, if they exist.
248
  ///
249
  /// Any errors are reported to the stream that was this object was
250
  /// constructed with.
251
  ///
252
  /// \returns true if the existing Apple-style accelerator tables verify
253
  /// successfully, false otherwise.
254
  bool handleAccelTables();
255
};
256
257
static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS,
258
629
                             const DWARFVerifier::DieRangeInfo &RHS) {
259
629
  return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die);
260
629
}
Unexecuted instantiation: DWARFContext.cpp:llvm::operator<(llvm::DWARFVerifier::DieRangeInfo const&, llvm::DWARFVerifier::DieRangeInfo const&)
DWARFVerifier.cpp:llvm::operator<(llvm::DWARFVerifier::DieRangeInfo const&, llvm::DWARFVerifier::DieRangeInfo const&)
Line
Count
Source
258
629
                             const DWARFVerifier::DieRangeInfo &RHS) {
259
629
  return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die);
260
629
}
261
262
} // end namespace llvm
263
264
#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H