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 ¬e() 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