xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/ADT/StringMap.h"
13 #include "llvm/DebugInfo/DIContext.h"
14 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
15 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
16 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
17 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
18 #include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
19 #include "llvm/Support/Compiler.h"
20 #include <cstdint>
21 #include <map>
22 #include <mutex>
23 #include <set>
24 
25 namespace llvm {
26 class raw_ostream;
27 struct DWARFAddressRange;
28 class DWARFUnit;
29 class DWARFUnitVector;
30 struct DWARFAttribute;
31 class DWARFContext;
32 class DWARFDataExtractor;
33 class DWARFDebugAbbrev;
34 class DataExtractor;
35 struct DWARFSection;
36 
37 struct AggregationData {
38   unsigned OverallCount;
39   std::map<std::string, unsigned> DetailedCounts;
40 };
41 
42 class OutputCategoryAggregator {
43 private:
44   std::mutex WriteMutex;
45   std::map<std::string, AggregationData, std::less<>> Aggregation;
46   uint64_t NumErrors = 0;
47   bool IncludeDetail;
48 
49 public:
50   OutputCategoryAggregator(bool includeDetail = false)
IncludeDetail(includeDetail)51       : IncludeDetail(includeDetail) {}
ShowDetail(bool showDetail)52   void ShowDetail(bool showDetail) { IncludeDetail = showDetail; }
GetNumCategories()53   size_t GetNumCategories() const { return Aggregation.size(); }
54   LLVM_ABI void Report(StringRef category,
55                        std::function<void()> detailCallback);
56   LLVM_ABI void Report(StringRef category, StringRef sub_category,
57                        std::function<void()> detailCallback);
58   LLVM_ABI void
59   EnumerateResults(std::function<void(StringRef, unsigned)> handleCounts);
60   LLVM_ABI void EnumerateDetailedResultsFor(
61       StringRef category,
62       std::function<void(StringRef, unsigned)> handleCounts);
63   /// Return the number of errors that have been reported.
GetNumErrors()64   uint64_t GetNumErrors() const { return NumErrors; }
65 };
66 
67 /// A class that verifies DWARF debug information given a DWARF Context.
68 class DWARFVerifier {
69 public:
70   /// A class that keeps the address range information for a single DIE.
71   struct DieRangeInfo {
72     DWARFDie Die;
73 
74     /// Sorted DWARFAddressRanges.
75     std::vector<DWARFAddressRange> Ranges;
76 
77     /// Sorted DWARFAddressRangeInfo.
78     std::set<DieRangeInfo> Children;
79 
80     DieRangeInfo() = default;
DieRangeInfoDieRangeInfo81     DieRangeInfo(DWARFDie Die) : Die(Die) {}
82 
83     /// Used for unit testing.
DieRangeInfoDieRangeInfo84     DieRangeInfo(std::vector<DWARFAddressRange> Ranges)
85         : Ranges(std::move(Ranges)) {}
86 
87     typedef std::set<DieRangeInfo>::const_iterator die_range_info_iterator;
88 
89     /// Inserts the address range. If the range overlaps with an existing
90     /// range, the range that it overlaps with will be returned and the two
91     /// address ranges will be unioned together in "Ranges". If a duplicate
92     /// entry is attempted to be added, the duplicate range will not actually be
93     /// added and the returned iterator will point to end().
94     ///
95     /// This is used for finding overlapping ranges in the DW_AT_ranges
96     /// attribute of a DIE. It is also used as a set of address ranges that
97     /// children address ranges must all be contained in.
98     LLVM_ABI std::optional<DWARFAddressRange>
99     insert(const DWARFAddressRange &R);
100 
101     /// Inserts the address range info. If any of its ranges overlaps with a
102     /// range in an existing range info, the range info is *not* added and an
103     /// iterator to the overlapping range info. If a duplicate entry is
104     /// attempted to be added, the duplicate range will not actually be added
105     /// and the returned iterator will point to end().
106     ///
107     /// This is used for finding overlapping children of the same DIE.
108     LLVM_ABI die_range_info_iterator insert(const DieRangeInfo &RI);
109 
110     /// Return true if ranges in this object contains all ranges within RHS.
111     LLVM_ABI bool contains(const DieRangeInfo &RHS) const;
112 
113     /// Return true if any range in this object intersects with any range in
114     /// RHS. Identical ranges are not considered to be intersecting.
115     LLVM_ABI bool intersects(const DieRangeInfo &RHS) const;
116   };
117 
118 private:
119   raw_ostream &OS;
120   DWARFContext &DCtx;
121   DIDumpOptions DumpOpts;
122   uint32_t NumDebugLineErrors = 0;
123   OutputCategoryAggregator ErrorCategory;
124   // Used to relax some checks that do not currently work portably
125   bool IsObjectFile;
126   bool IsMachOObject;
127   using ReferenceMap = std::map<uint64_t, std::set<uint64_t>>;
128   std::mutex AccessMutex;
129 
130   raw_ostream &error() const;
131   raw_ostream &warn() const;
132   raw_ostream &note() const;
133   raw_ostream &dump(const DWARFDie &Die, unsigned indent = 0) const;
134 
135   /// Verifies the abbreviations section.
136   ///
137   /// This function currently checks that:
138   /// --No abbreviation declaration has more than one attributes with the same
139   /// name.
140   ///
141   /// \param Abbrev Pointer to the abbreviations section we are verifying
142   /// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo.
143   ///
144   /// \returns The number of errors that occurred during verification.
145   unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev);
146 
147   /// Verifies the header of a unit in a .debug_info or .debug_types section.
148   ///
149   /// This function currently checks for:
150   /// - Unit is in 32-bit DWARF format. The function can be modified to
151   /// support 64-bit format.
152   /// - The DWARF version is valid
153   /// - The unit type is valid (if unit is in version >=5)
154   /// - The unit doesn't extend beyond the containing section
155   /// - The address size is valid
156   /// - The offset in the .debug_abbrev section is valid
157   ///
158   /// \param DebugInfoData The section data
159   /// \param Offset A reference to the offset start of the unit. The offset will
160   /// be updated to point to the next unit in the section
161   /// \param UnitIndex The index of the unit to be verified
162   /// \param UnitType A reference to the type of the unit
163   /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is
164   /// in 64-bit format.
165   ///
166   /// \returns true if the header is verified successfully, false otherwise.
167   bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
168                         uint64_t *Offset, unsigned UnitIndex, uint8_t &UnitType,
169                         bool &isUnitDWARF64);
170   bool verifyName(const DWARFDie &Die);
171 
172   /// Verifies the header of a unit in a .debug_info or .debug_types section.
173   ///
174   /// This function currently verifies:
175   ///  - The debug info attributes.
176   ///  - The debug info form=s.
177   ///  - The presence of a root DIE.
178   ///  - That the root DIE is a unit DIE.
179   ///  - If a unit type is provided, that the unit DIE matches the unit type.
180   ///  - The DIE ranges.
181   ///  - That call site entries are only nested within subprograms with a
182   ///    DW_AT_call attribute.
183   ///
184   /// \param Unit      The DWARF Unit to verify.
185   ///
186   /// \returns The number of errors that occurred during verification.
187   unsigned verifyUnitContents(DWARFUnit &Unit,
188                               ReferenceMap &UnitLocalReferences,
189                               ReferenceMap &CrossUnitReferences);
190 
191   /// Verifies the unit headers and contents in a .debug_info or .debug_types
192   /// section.
193   ///
194   /// \param S           The DWARF Section to verify.
195   ///
196   /// \returns The number of errors that occurred during verification.
197   unsigned verifyUnitSection(const DWARFSection &S);
198   unsigned verifyUnits(const DWARFUnitVector &Units);
199 
200   unsigned verifyIndex(StringRef Name, DWARFSectionKind SectionKind,
201                        StringRef Index);
202 
203   /// Verifies that a call site entry is nested within a subprogram with a
204   /// DW_AT_call attribute.
205   ///
206   /// \returns Number of errors that occurred during verification.
207   unsigned verifyDebugInfoCallSite(const DWARFDie &Die);
208 
209   /// Verify that all Die ranges are valid.
210   ///
211   /// This function currently checks for:
212   /// - cases in which lowPC >= highPC
213   ///
214   /// \returns Number of errors that occurred during verification.
215   unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI);
216 
217   /// Verifies the attribute's DWARF attribute and its value.
218   ///
219   /// This function currently checks for:
220   /// - DW_AT_ranges values is a valid .debug_ranges offset
221   /// - DW_AT_stmt_list is a valid .debug_line offset
222   ///
223   /// \param Die          The DWARF DIE that owns the attribute value
224   /// \param AttrValue    The DWARF attribute value to check
225   ///
226   /// \returns NumErrors The number of errors occurred during verification of
227   /// attributes' values in a unit
228   unsigned verifyDebugInfoAttribute(const DWARFDie &Die,
229                                     DWARFAttribute &AttrValue);
230 
231   /// Verifies the attribute's DWARF form.
232   ///
233   /// This function currently checks for:
234   /// - All DW_FORM_ref values that are CU relative have valid CU offsets
235   /// - All DW_FORM_ref_addr values have valid section offsets
236   /// - All DW_FORM_strp values have valid .debug_str offsets
237   ///
238   /// \param Die          The DWARF DIE that owns the attribute value
239   /// \param AttrValue    The DWARF attribute value to check
240   ///
241   /// \returns NumErrors The number of errors occurred during verification of
242   /// attributes' forms in a unit
243   unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue,
244                                ReferenceMap &UnitLocalReferences,
245                                ReferenceMap &CrossUnitReferences);
246 
247   /// Verifies the all valid references that were found when iterating through
248   /// all of the DIE attributes.
249   ///
250   /// This function will verify that all references point to DIEs whose DIE
251   /// offset matches. This helps to ensure if a DWARF link phase moved things
252   /// around, that it doesn't create invalid references by failing to relocate
253   /// CU relative and absolute references.
254   ///
255   /// \returns NumErrors The number of errors occurred during verification of
256   /// references for the .debug_info and .debug_types sections
257   unsigned verifyDebugInfoReferences(
258       const ReferenceMap &,
259       llvm::function_ref<DWARFUnit *(uint64_t)> GetUnitForDieOffset);
260 
261   /// Verify the DW_AT_stmt_list encoding and value and ensure that no
262   /// compile units that have the same DW_AT_stmt_list value.
263   void verifyDebugLineStmtOffsets();
264 
265   /// Verify that all of the rows in the line table are valid.
266   ///
267   /// This function currently checks for:
268   /// - addresses within a sequence that decrease in value
269   /// - invalid file indexes
270   void verifyDebugLineRows();
271 
272   /// Verify that an Apple-style accelerator table is valid.
273   ///
274   /// This function currently checks that:
275   /// - The fixed part of the header fits in the section
276   /// - The size of the section is as large as what the header describes
277   /// - There is at least one atom
278   /// - The form for each atom is valid
279   /// - The tag for each DIE in the table is valid
280   /// - The buckets have a valid index, or they are empty
281   /// - Each hashdata offset is valid
282   /// - Each DIE is valid
283   ///
284   /// \param AccelSection pointer to the section containing the acceleration table
285   /// \param StrData pointer to the string section
286   /// \param SectionName the name of the table we're verifying
287   ///
288   /// \returns The number of errors occurred during verification
289   void verifyAppleAccelTable(const DWARFSection *AccelSection,
290                              DataExtractor *StrData, const char *SectionName);
291 
292   void verifyDebugNamesCULists(const DWARFDebugNames &AccelTable);
293   void verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
294                               const DataExtractor &StrData);
295   void verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI);
296   void verifyNameIndexAttribute(const DWARFDebugNames::NameIndex &NI,
297                                 const DWARFDebugNames::Abbrev &Abbr,
298                                 DWARFDebugNames::AttributeEncoding AttrEnc);
299   void verifyNameIndexEntries(
300       const DWARFDebugNames::NameIndex &NI,
301       const DWARFDebugNames::NameTableEntry &NTE,
302       const DenseMap<uint64_t, DWARFUnit *> &CUOffsetsToDUMap);
303   void verifyNameIndexCompleteness(
304       const DWARFDie &Die, const DWARFDebugNames::NameIndex &NI,
305       const StringMap<DenseSet<uint64_t>> &NamesToDieOffsets);
306 
307   /// Verify that the DWARF v5 accelerator table is valid.
308   ///
309   /// This function currently checks that:
310   /// - Headers individual Name Indices fit into the section and can be parsed.
311   /// - Abbreviation tables can be parsed and contain valid index attributes
312   ///   with correct form encodings.
313   /// - The CU lists reference existing compile units.
314   /// - The buckets have a valid index, or they are empty.
315   /// - All names are reachable via the hash table (they have the correct hash,
316   ///   and the hash is in the correct bucket).
317   /// - Information in the index entries is complete (all required entries are
318   ///   present) and consistent with the debug_info section DIEs.
319   ///
320   /// \param AccelSection section containing the acceleration table
321   /// \param StrData string section
322   ///
323   /// \returns The number of errors occurred during verification
324   void verifyDebugNames(const DWARFSection &AccelSection,
325                         const DataExtractor &StrData);
326 
327   /// Verify that the the expression is valid within the context of unit U.
328   ///
329   /// \param E expression to verify.
330   /// \param U containing DWARFUnit, if any.
331   ///
332   /// returns true if E is a valid expression.
333   bool verifyExpression(const DWARFExpression &E, DWARFUnit *U);
334 
335   /// Verify that the the expression operation is valid within the context of
336   /// unit U.
337   ///
338   /// \param Op operation to verify
339   /// \param U containing DWARFUnit, if any
340   ///
341   /// returns true if Op is a valid Dwarf operation
342   bool verifyExpressionOp(const DWARFExpression::Operation &Op, DWARFUnit *U);
343 
344 public:
345   LLVM_ABI
346   DWARFVerifier(raw_ostream &S, DWARFContext &D,
347                 DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE());
348 
349   /// Verify the information in any of the following sections, if available:
350   /// .debug_abbrev, debug_abbrev.dwo
351   ///
352   /// Any errors are reported to the stream that was this object was
353   /// constructed with.
354   ///
355   /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully,
356   /// false otherwise.
357   LLVM_ABI bool handleDebugAbbrev();
358 
359   /// Verify the information in the .debug_info and .debug_types sections.
360   ///
361   /// Any errors are reported to the stream that this object was
362   /// constructed with.
363   ///
364   /// \returns true if all sections verify successfully, false otherwise.
365   LLVM_ABI bool handleDebugInfo();
366 
367   /// Verify the information in the .debug_cu_index section.
368   ///
369   /// Any errors are reported to the stream that was this object was
370   /// constructed with.
371   ///
372   /// \returns true if the .debug_cu_index verifies successfully, false
373   /// otherwise.
374   LLVM_ABI bool handleDebugCUIndex();
375 
376   /// Verify the information in the .debug_tu_index section.
377   ///
378   /// Any errors are reported to the stream that was this object was
379   /// constructed with.
380   ///
381   /// \returns true if the .debug_tu_index verifies successfully, false
382   /// otherwise.
383   LLVM_ABI bool handleDebugTUIndex();
384 
385   /// Verify the information in the .debug_line section.
386   ///
387   /// Any errors are reported to the stream that was this object was
388   /// constructed with.
389   ///
390   /// \returns true if the .debug_line verifies successfully, false otherwise.
391   LLVM_ABI bool handleDebugLine();
392 
393   /// Verify the information in accelerator tables, if they exist.
394   ///
395   /// Any errors are reported to the stream that was this object was
396   /// constructed with.
397   ///
398   /// \returns true if the existing Apple-style accelerator tables verify
399   /// successfully, false otherwise.
400   LLVM_ABI bool handleAccelTables();
401 
402   /// Verify the information in the .debug_str_offsets[.dwo].
403   ///
404   /// Any errors are reported to the stream that was this object was
405   /// constructed with.
406   ///
407   /// \returns true if the .debug_line verifies successfully, false otherwise.
408   LLVM_ABI bool handleDebugStrOffsets();
409   LLVM_ABI bool
410   verifyDebugStrOffsets(std::optional<dwarf::DwarfFormat> LegacyFormat,
411                         StringRef SectionName, const DWARFSection &Section,
412                         StringRef StrData);
413 
414   /// Emits any aggregate information collected, depending on the dump options
415   LLVM_ABI void summarize();
416 };
417 
418 static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS,
419                              const DWARFVerifier::DieRangeInfo &RHS) {
420   return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die);
421 }
422 
423 } // end namespace llvm
424 
425 #endif // LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
426