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 /// Verify the information in the .debug_str_offsets[.dwo]. 343 /// 344 /// Any errors are reported to the stream that was this object was 345 /// constructed with. 346 /// 347 /// \returns true if the .debug_line verifies successfully, false otherwise. 348 bool handleDebugStrOffsets(); 349 bool verifyDebugStrOffsets( 350 StringRef SectionName, const DWARFSection &Section, StringRef StrData, 351 void (DWARFObject::*)(function_ref<void(const DWARFSection &)>) const); 352 }; 353 354 static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS, 355 const DWARFVerifier::DieRangeInfo &RHS) { 356 return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die); 357 } 358 359 } // end namespace llvm 360 361 #endif // LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H 362