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
21namespace llvm {
22class raw_ostream;
23struct DWARFAttribute;
24class DWARFContext;
25class DWARFDie;
26class DWARFUnit;
27class DWARFAcceleratorTable;
28class DWARFDataExtractor;
29class DWARFDebugAbbrev;
30class DataExtractor;
31struct DWARFSection;
32
33/// A class that verifies DWARF debug information given a DWARF Context.
34class DWARFVerifier {
35public:
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    DieRangeInfo() = default;
47    DieRangeInfo(DWARFDie Die) : Die(Die) {}
48
49    /// Used for unit testing.
50    DieRangeInfo(std::vector<DWARFAddressRange> Ranges)
51        : 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    address_range_iterator findRange(const DWARFAddressRange &R) const {
66      auto Begin = Ranges.begin();
67      auto End = Ranges.end();
68      auto Iter = std::upper_bound(Begin, End, R);
69      if (Iter != Begin)
70        --Iter;
71      return Iter;
72    }
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
89private:
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  raw_ostream &error() const;
100  raw_ostream &warn() const;
101  raw_ostream &note() const;
102
103  /// Verifies the abbreviations section.
104  ///
105  /// This function currently checks that:
106  /// --No abbreviation declaration has more than one attributes with the same
107  /// name.
108  ///
109  /// \param Abbrev Pointer to the abbreviations section we are verifying
110  /// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo.
111  ///
112  /// \returns The number of errors that occured during verification.
113  unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev);
114
115  /// Verifies the header of a unit in the .debug_info section.
116  ///
117  /// This function currently checks for:
118  /// - Unit is in 32-bit DWARF format. The function can be modified to
119  /// support 64-bit format.
120  /// - The DWARF version is valid
121  /// - The unit type is valid (if unit is in version >=5)
122  /// - The unit doesn't extend beyond .debug_info section
123  /// - The address size is valid
124  /// - The offset in the .debug_abbrev section is valid
125  ///
126  /// \param DebugInfoData The .debug_info section data
127  /// \param Offset A reference to the offset start of the unit. The offset will
128  /// be updated to point to the next unit in .debug_info
129  /// \param UnitIndex The index of the unit to be verified
130  /// \param UnitType A reference to the type of the unit
131  /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is
132  /// in 64-bit format.
133  ///
134  /// \returns true if the header is verified successfully, false otherwise.
135  bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
136                        uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType,
137                        bool &isUnitDWARF64);
138
139  /// Verifies the header of a unit in the .debug_info section.
140  ///
141  /// This function currently verifies:
142  ///  - The debug info attributes.
143  ///  - The debug info form=s.
144  ///  - The presence of a root DIE.
145  ///  - That the root DIE is a unit DIE.
146  ///  - If a unit type is provided, that the unit DIE matches the unit type.
147  ///  - The DIE ranges.
148  ///
149  /// \param Unit      The DWARF Unit to verifiy.
150  /// \param UnitType  An optional unit type which will be used to verify the
151  ///                  type of the unit DIE.
152  ///
153  /// \returns true if the content is verified successfully, false otherwise.
154  bool verifyUnitContents(DWARFUnit Unit, uint8_t UnitType = 0);
155
156  /// Verify that all Die ranges are valid.
157  ///
158  /// This function currently checks for:
159  /// - cases in which lowPC >= highPC
160  ///
161  /// \returns Number of errors that occured during verification.
162  unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI);
163
164  /// Verifies the attribute's DWARF attribute and its value.
165  ///
166  /// This function currently checks for:
167  /// - DW_AT_ranges values is a valid .debug_ranges offset
168  /// - DW_AT_stmt_list is a valid .debug_line offset
169  ///
170  /// \param Die          The DWARF DIE that owns the attribute value
171  /// \param AttrValue    The DWARF attribute value to check
172  ///
173  /// \returns NumErrors The number of errors occured during verification of
174  /// attributes' values in a .debug_info section unit
175  unsigned verifyDebugInfoAttribute(const DWARFDie &Die,
176                                    DWARFAttribute &AttrValue);
177
178  /// Verifies the attribute's DWARF form.
179  ///
180  /// This function currently checks for:
181  /// - All DW_FORM_ref values that are CU relative have valid CU offsets
182  /// - All DW_FORM_ref_addr values have valid .debug_info offsets
183  /// - All DW_FORM_strp values have valid .debug_str offsets
184  ///
185  /// \param Die          The DWARF DIE that owns the attribute value
186  /// \param AttrValue    The DWARF attribute value to check
187  ///
188  /// \returns NumErrors The number of errors occured during verification of
189  /// attributes' forms in a .debug_info section unit
190  unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue);
191
192  /// Verifies the all valid references that were found when iterating through
193  /// all of the DIE attributes.
194  ///
195  /// This function will verify that all references point to DIEs whose DIE
196  /// offset matches. This helps to ensure if a DWARF link phase moved things
197  /// around, that it doesn't create invalid references by failing to relocate
198  /// CU relative and absolute references.
199  ///
200  /// \returns NumErrors The number of errors occured during verification of
201  /// references for the .debug_info section
202  unsigned verifyDebugInfoReferences();
203
204  /// Verify the the DW_AT_stmt_list encoding and value and ensure that no
205  /// compile units that have the same DW_AT_stmt_list value.
206  void verifyDebugLineStmtOffsets();
207
208  /// Verify that all of the rows in the line table are valid.
209  ///
210  /// This function currently checks for:
211  /// - addresses within a sequence that decrease in value
212  /// - invalid file indexes
213  void verifyDebugLineRows();
214
215  /// Verify that an Apple-style accelerator table is valid.
216  ///
217  /// This function currently checks that:
218  /// - The fixed part of the header fits in the section
219  /// - The size of the section is as large as what the header describes
220  /// - There is at least one atom
221  /// - The form for each atom is valid
222  /// - The tag for each DIE in the table is valid
223  /// - The buckets have a valid index, or they are empty
224  /// - Each hashdata offset is valid
225  /// - Each DIE is valid
226  ///
227  /// \param AccelSection pointer to the section containing the acceleration table
228  /// \param StrData pointer to the string section
229  /// \param SectionName the name of the table we're verifying
230  ///
231  /// \returns The number of errors occured during verification
232  unsigned verifyAccelTable(const DWARFSection *AccelSection,
233                            DataExtractor *StrData, const char *SectionName);
234
235public:
236  DWARFVerifier(raw_ostream &S, DWARFContext &D,
237                DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE())
238      : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)) {}
239  /// Verify the information in any of the following sections, if available:
240  /// .debug_abbrev, debug_abbrev.dwo
241  ///
242  /// Any errors are reported to the stream that was this object was
243  /// constructed with.
244  ///
245  /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully,
246  /// false otherwise.
247  bool handleDebugAbbrev();
248
249  /// Verify the information in the .debug_info section.
250  ///
251  /// Any errors are reported to the stream that was this object was
252  /// constructed with.
253  ///
254  /// \returns true if the .debug_info verifies successfully, false otherwise.
255  bool handleDebugInfo();
256
257  /// Verify the information in the .debug_line section.
258  ///
259  /// Any errors are reported to the stream that was this object was
260  /// constructed with.
261  ///
262  /// \returns true if the .debug_line verifies successfully, false otherwise.
263  bool handleDebugLine();
264
265  /// Verify the information in accelerator tables, if they exist.
266  ///
267  /// Any errors are reported to the stream that was this object was
268  /// constructed with.
269  ///
270  /// \returns true if the existing Apple-style accelerator tables verify
271  /// successfully, false otherwise.
272  bool handleAccelTables();
273};
274
275static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS,
276                             const DWARFVerifier::DieRangeInfo &RHS) {
277  return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die);
278}
279
280} // end namespace llvm
281
282#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
283