Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- DWARFVerifier.h ----------------------------------------------------===// |
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_DWARF_DWARFVERIFIER_H |
||
10 | #define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H |
||
11 | |||
12 | #include "llvm/DebugInfo/DIContext.h" |
||
13 | #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" |
||
14 | #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" |
||
15 | #include "llvm/DebugInfo/DWARF/DWARFDie.h" |
||
16 | #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" |
||
17 | #include <cstdint> |
||
18 | #include <map> |
||
19 | #include <set> |
||
20 | |||
21 | namespace llvm { |
||
22 | class raw_ostream; |
||
23 | struct DWARFAddressRange; |
||
24 | class DWARFUnit; |
||
25 | class DWARFUnitVector; |
||
26 | struct DWARFAttribute; |
||
27 | class DWARFContext; |
||
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 | 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::set<DieRangeInfo>::const_iterator die_range_info_iterator; |
||
54 | |||
55 | /// Inserts the address range. If the range overlaps with an existing |
||
56 | /// range, the range that it overlaps with will be returned and the two |
||
57 | /// address ranges will be unioned together in "Ranges". |
||
58 | /// |
||
59 | /// This is used for finding overlapping ranges in the DW_AT_ranges |
||
60 | /// attribute of a DIE. It is also used as a set of address ranges that |
||
61 | /// children address ranges must all be contained in. |
||
62 | std::optional<DWARFAddressRange> insert(const DWARFAddressRange &R); |
||
63 | |||
64 | /// Inserts the address range info. If any of its ranges overlaps with a |
||
65 | /// range in an existing range info, the range info is *not* added and an |
||
66 | /// iterator to the overlapping range info. |
||
67 | /// |
||
68 | /// This is used for finding overlapping children of the same DIE. |
||
69 | die_range_info_iterator insert(const DieRangeInfo &RI); |
||
70 | |||
71 | /// Return true if ranges in this object contains all ranges within RHS. |
||
72 | bool contains(const DieRangeInfo &RHS) const; |
||
73 | |||
74 | /// Return true if any range in this object intersects with any range in |
||
75 | /// RHS. |
||
76 | bool intersects(const DieRangeInfo &RHS) const; |
||
77 | }; |
||
78 | |||
79 | private: |
||
80 | raw_ostream &OS; |
||
81 | DWARFContext &DCtx; |
||
82 | DIDumpOptions DumpOpts; |
||
83 | uint32_t NumDebugLineErrors = 0; |
||
84 | // Used to relax some checks that do not currently work portably |
||
85 | bool IsObjectFile; |
||
86 | bool IsMachOObject; |
||
87 | using ReferenceMap = std::map<uint64_t, std::set<uint64_t>>; |
||
88 | |||
89 | raw_ostream &error() const; |
||
90 | raw_ostream &warn() const; |
||
91 | raw_ostream ¬e() const; |
||
92 | raw_ostream &dump(const DWARFDie &Die, unsigned indent = 0) const; |
||
93 | |||
94 | /// Verifies the abbreviations section. |
||
95 | /// |
||
96 | /// This function currently checks that: |
||
97 | /// --No abbreviation declaration has more than one attributes with the same |
||
98 | /// name. |
||
99 | /// |
||
100 | /// \param Abbrev Pointer to the abbreviations section we are verifying |
||
101 | /// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo. |
||
102 | /// |
||
103 | /// \returns The number of errors that occurred during verification. |
||
104 | unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev); |
||
105 | |||
106 | /// Verifies the header of a unit in a .debug_info or .debug_types section. |
||
107 | /// |
||
108 | /// This function currently checks for: |
||
109 | /// - Unit is in 32-bit DWARF format. The function can be modified to |
||
110 | /// support 64-bit format. |
||
111 | /// - The DWARF version is valid |
||
112 | /// - The unit type is valid (if unit is in version >=5) |
||
113 | /// - The unit doesn't extend beyond the containing section |
||
114 | /// - The address size is valid |
||
115 | /// - The offset in the .debug_abbrev section is valid |
||
116 | /// |
||
117 | /// \param DebugInfoData The section data |
||
118 | /// \param Offset A reference to the offset start of the unit. The offset will |
||
119 | /// be updated to point to the next unit in the section |
||
120 | /// \param UnitIndex The index of the unit to be verified |
||
121 | /// \param UnitType A reference to the type of the unit |
||
122 | /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is |
||
123 | /// in 64-bit format. |
||
124 | /// |
||
125 | /// \returns true if the header is verified successfully, false otherwise. |
||
126 | bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData, |
||
127 | uint64_t *Offset, unsigned UnitIndex, uint8_t &UnitType, |
||
128 | bool &isUnitDWARF64); |
||
129 | bool verifyName(const DWARFDie &Die); |
||
130 | |||
131 | /// Verifies the header of a unit in a .debug_info or .debug_types section. |
||
132 | /// |
||
133 | /// This function currently verifies: |
||
134 | /// - The debug info attributes. |
||
135 | /// - The debug info form=s. |
||
136 | /// - The presence of a root DIE. |
||
137 | /// - That the root DIE is a unit DIE. |
||
138 | /// - If a unit type is provided, that the unit DIE matches the unit type. |
||
139 | /// - The DIE ranges. |
||
140 | /// - That call site entries are only nested within subprograms with a |
||
141 | /// DW_AT_call attribute. |
||
142 | /// |
||
143 | /// \param Unit The DWARF Unit to verify. |
||
144 | /// |
||
145 | /// \returns The number of errors that occurred during verification. |
||
146 | unsigned verifyUnitContents(DWARFUnit &Unit, |
||
147 | ReferenceMap &UnitLocalReferences, |
||
148 | ReferenceMap &CrossUnitReferences); |
||
149 | |||
150 | /// Verifies the unit headers and contents in a .debug_info or .debug_types |
||
151 | /// section. |
||
152 | /// |
||
153 | /// \param S The DWARF Section to verify. |
||
154 | /// |
||
155 | /// \returns The number of errors that occurred during verification. |
||
156 | unsigned verifyUnitSection(const DWARFSection &S); |
||
157 | unsigned verifyUnits(const DWARFUnitVector &Units); |
||
158 | |||
159 | unsigned verifyIndexes(const DWARFObject &DObj); |
||
160 | unsigned verifyIndex(StringRef Name, DWARFSectionKind SectionKind, |
||
161 | StringRef Index); |
||
162 | |||
163 | /// Verifies that a call site entry is nested within a subprogram with a |
||
164 | /// DW_AT_call attribute. |
||
165 | /// |
||
166 | /// \returns Number of errors that occurred during verification. |
||
167 | unsigned verifyDebugInfoCallSite(const DWARFDie &Die); |
||
168 | |||
169 | /// Verify that all Die ranges are valid. |
||
170 | /// |
||
171 | /// This function currently checks for: |
||
172 | /// - cases in which lowPC >= highPC |
||
173 | /// |
||
174 | /// \returns Number of errors that occurred during verification. |
||
175 | unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI); |
||
176 | |||
177 | /// Verifies the attribute's DWARF attribute and its value. |
||
178 | /// |
||
179 | /// This function currently checks for: |
||
180 | /// - DW_AT_ranges values is a valid .debug_ranges offset |
||
181 | /// - DW_AT_stmt_list is a valid .debug_line offset |
||
182 | /// |
||
183 | /// \param Die The DWARF DIE that owns the attribute value |
||
184 | /// \param AttrValue The DWARF attribute value to check |
||
185 | /// |
||
186 | /// \returns NumErrors The number of errors occurred during verification of |
||
187 | /// attributes' values in a unit |
||
188 | unsigned verifyDebugInfoAttribute(const DWARFDie &Die, |
||
189 | DWARFAttribute &AttrValue); |
||
190 | |||
191 | /// Verifies the attribute's DWARF form. |
||
192 | /// |
||
193 | /// This function currently checks for: |
||
194 | /// - All DW_FORM_ref values that are CU relative have valid CU offsets |
||
195 | /// - All DW_FORM_ref_addr values have valid section offsets |
||
196 | /// - All DW_FORM_strp values have valid .debug_str offsets |
||
197 | /// |
||
198 | /// \param Die The DWARF DIE that owns the attribute value |
||
199 | /// \param AttrValue The DWARF attribute value to check |
||
200 | /// |
||
201 | /// \returns NumErrors The number of errors occurred during verification of |
||
202 | /// attributes' forms in a unit |
||
203 | unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue, |
||
204 | ReferenceMap &UnitLocalReferences, |
||
205 | ReferenceMap &CrossUnitReferences); |
||
206 | |||
207 | /// Verifies the all valid references that were found when iterating through |
||
208 | /// all of the DIE attributes. |
||
209 | /// |
||
210 | /// This function will verify that all references point to DIEs whose DIE |
||
211 | /// offset matches. This helps to ensure if a DWARF link phase moved things |
||
212 | /// around, that it doesn't create invalid references by failing to relocate |
||
213 | /// CU relative and absolute references. |
||
214 | /// |
||
215 | /// \returns NumErrors The number of errors occurred during verification of |
||
216 | /// references for the .debug_info and .debug_types sections |
||
217 | unsigned verifyDebugInfoReferences( |
||
218 | const ReferenceMap &, |
||
219 | llvm::function_ref<DWARFUnit *(uint64_t)> GetUnitForDieOffset); |
||
220 | |||
221 | /// Verify the DW_AT_stmt_list encoding and value and ensure that no |
||
222 | /// compile units that have the same DW_AT_stmt_list value. |
||
223 | void verifyDebugLineStmtOffsets(); |
||
224 | |||
225 | /// Verify that all of the rows in the line table are valid. |
||
226 | /// |
||
227 | /// This function currently checks for: |
||
228 | /// - addresses within a sequence that decrease in value |
||
229 | /// - invalid file indexes |
||
230 | void verifyDebugLineRows(); |
||
231 | |||
232 | /// Verify that an Apple-style accelerator table is valid. |
||
233 | /// |
||
234 | /// This function currently checks that: |
||
235 | /// - The fixed part of the header fits in the section |
||
236 | /// - The size of the section is as large as what the header describes |
||
237 | /// - There is at least one atom |
||
238 | /// - The form for each atom is valid |
||
239 | /// - The tag for each DIE in the table is valid |
||
240 | /// - The buckets have a valid index, or they are empty |
||
241 | /// - Each hashdata offset is valid |
||
242 | /// - Each DIE is valid |
||
243 | /// |
||
244 | /// \param AccelSection pointer to the section containing the acceleration table |
||
245 | /// \param StrData pointer to the string section |
||
246 | /// \param SectionName the name of the table we're verifying |
||
247 | /// |
||
248 | /// \returns The number of errors occurred during verification |
||
249 | unsigned verifyAppleAccelTable(const DWARFSection *AccelSection, |
||
250 | DataExtractor *StrData, |
||
251 | const char *SectionName); |
||
252 | |||
253 | unsigned verifyDebugNamesCULists(const DWARFDebugNames &AccelTable); |
||
254 | unsigned verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI, |
||
255 | const DataExtractor &StrData); |
||
256 | unsigned verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI); |
||
257 | unsigned verifyNameIndexAttribute(const DWARFDebugNames::NameIndex &NI, |
||
258 | const DWARFDebugNames::Abbrev &Abbr, |
||
259 | DWARFDebugNames::AttributeEncoding AttrEnc); |
||
260 | unsigned verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI, |
||
261 | const DWARFDebugNames::NameTableEntry &NTE); |
||
262 | unsigned verifyNameIndexCompleteness(const DWARFDie &Die, |
||
263 | const DWARFDebugNames::NameIndex &NI); |
||
264 | |||
265 | /// Verify that the DWARF v5 accelerator table is valid. |
||
266 | /// |
||
267 | /// This function currently checks that: |
||
268 | /// - Headers individual Name Indices fit into the section and can be parsed. |
||
269 | /// - Abbreviation tables can be parsed and contain valid index attributes |
||
270 | /// with correct form encodings. |
||
271 | /// - The CU lists reference existing compile units. |
||
272 | /// - The buckets have a valid index, or they are empty. |
||
273 | /// - All names are reachable via the hash table (they have the correct hash, |
||
274 | /// and the hash is in the correct bucket). |
||
275 | /// - Information in the index entries is complete (all required entries are |
||
276 | /// present) and consistent with the debug_info section DIEs. |
||
277 | /// |
||
278 | /// \param AccelSection section containing the acceleration table |
||
279 | /// \param StrData string section |
||
280 | /// |
||
281 | /// \returns The number of errors occurred during verification |
||
282 | unsigned verifyDebugNames(const DWARFSection &AccelSection, |
||
283 | const DataExtractor &StrData); |
||
284 | |||
285 | public: |
||
286 | DWARFVerifier(raw_ostream &S, DWARFContext &D, |
||
287 | DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE()); |
||
288 | |||
289 | /// Verify the information in any of the following sections, if available: |
||
290 | /// .debug_abbrev, debug_abbrev.dwo |
||
291 | /// |
||
292 | /// Any errors are reported to the stream that was this object was |
||
293 | /// constructed with. |
||
294 | /// |
||
295 | /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully, |
||
296 | /// false otherwise. |
||
297 | bool handleDebugAbbrev(); |
||
298 | |||
299 | /// Verify the information in the .debug_info and .debug_types sections. |
||
300 | /// |
||
301 | /// Any errors are reported to the stream that this object was |
||
302 | /// constructed with. |
||
303 | /// |
||
304 | /// \returns true if all sections verify successfully, false otherwise. |
||
305 | bool handleDebugInfo(); |
||
306 | |||
307 | /// Verify the information in the .debug_cu_index section. |
||
308 | /// |
||
309 | /// Any errors are reported to the stream that was this object was |
||
310 | /// constructed with. |
||
311 | /// |
||
312 | /// \returns true if the .debug_cu_index verifies successfully, false |
||
313 | /// otherwise. |
||
314 | bool handleDebugCUIndex(); |
||
315 | |||
316 | /// Verify the information in the .debug_tu_index section. |
||
317 | /// |
||
318 | /// Any errors are reported to the stream that was this object was |
||
319 | /// constructed with. |
||
320 | /// |
||
321 | /// \returns true if the .debug_tu_index verifies successfully, false |
||
322 | /// otherwise. |
||
323 | bool handleDebugTUIndex(); |
||
324 | |||
325 | /// Verify the information in the .debug_line section. |
||
326 | /// |
||
327 | /// Any errors are reported to the stream that was this object was |
||
328 | /// constructed with. |
||
329 | /// |
||
330 | /// \returns true if the .debug_line verifies successfully, false otherwise. |
||
331 | bool handleDebugLine(); |
||
332 | |||
333 | /// Verify the information in accelerator tables, if they exist. |
||
334 | /// |
||
335 | /// Any errors are reported to the stream that was this object was |
||
336 | /// constructed with. |
||
337 | /// |
||
338 | /// \returns true if the existing Apple-style accelerator tables verify |
||
339 | /// successfully, false otherwise. |
||
340 | bool handleAccelTables(); |
||
341 | }; |
||
342 | |||
343 | static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS, |
||
344 | const DWARFVerifier::DieRangeInfo &RHS) { |
||
345 | return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die); |
||
346 | } |
||
347 | |||
348 | } // end namespace llvm |
||
349 | |||
350 | #endif // LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H |