/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 |