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/DWARFAcceleratorTable.h" 15 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" 16 #include "llvm/DebugInfo/DWARF/DWARFDie.h" 17 18 #include <cstdint> 19 #include <map> 20 #include <set> 21 22 namespace llvm { 23 class raw_ostream; 24 struct DWARFAttribute; 25 class DWARFContext; 26 class DWARFDie; 27 class DWARFUnit; 28 class DWARFCompileUnit; 29 class DWARFDataExtractor; 30 class DWARFDebugAbbrev; 31 class DataExtractor; 32 struct DWARFSection; 33 34 /// A class that verifies DWARF debug information given a DWARF Context. 35 class DWARFVerifier { 36 public: 37 /// A class that keeps the address range information for a single DIE. 38 struct DieRangeInfo { 39 DWARFDie Die; 40 41 /// Sorted DWARFAddressRanges. 42 std::vector<DWARFAddressRange> Ranges; 43 44 /// Sorted DWARFAddressRangeInfo. 45 std::set<DieRangeInfo> Children; 46 47 DieRangeInfo() = default; DieRangeInfoDieRangeInfo48 DieRangeInfo(DWARFDie Die) : Die(Die) {} 49 50 /// Used for unit testing. DieRangeInfoDieRangeInfo51 DieRangeInfo(std::vector<DWARFAddressRange> Ranges) 52 : Ranges(std::move(Ranges)) {} 53 54 typedef std::vector<DWARFAddressRange>::const_iterator 55 address_range_iterator; 56 typedef std::set<DieRangeInfo>::const_iterator die_range_info_iterator; 57 58 /// Inserts the address range. If the range overlaps with an existing 59 /// range, the range is *not* added and an iterator to the overlapping 60 /// range is returned. 61 /// 62 /// This is used for finding overlapping ranges within the same DIE. 63 address_range_iterator insert(const DWARFAddressRange &R); 64 65 /// Finds an address range in the sorted vector of ranges. findRangeDieRangeInfo66 address_range_iterator findRange(const DWARFAddressRange &R) const { 67 auto Begin = Ranges.begin(); 68 auto End = Ranges.end(); 69 auto Iter = std::upper_bound(Begin, End, R); 70 if (Iter != Begin) 71 --Iter; 72 return Iter; 73 } 74 75 /// Inserts the address range info. If any of its ranges overlaps with a 76 /// range in an existing range info, the range info is *not* added and an 77 /// iterator to the overlapping range info. 78 /// 79 /// This is used for finding overlapping children of the same DIE. 80 die_range_info_iterator insert(const DieRangeInfo &RI); 81 82 /// Return true if ranges in this object contains all ranges within RHS. 83 bool contains(const DieRangeInfo &RHS) const; 84 85 /// Return true if any range in this object intersects with any range in 86 /// RHS. 87 bool intersects(const DieRangeInfo &RHS) const; 88 }; 89 90 private: 91 raw_ostream &OS; 92 DWARFContext &DCtx; 93 DIDumpOptions DumpOpts; 94 /// A map that tracks all references (converted absolute references) so we 95 /// can verify each reference points to a valid DIE and not an offset that 96 /// lies between to valid DIEs. 97 std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets; 98 uint32_t NumDebugLineErrors = 0; 99 100 raw_ostream &error() const; 101 raw_ostream &warn() const; 102 raw_ostream ¬e() const; 103 104 /// Verifies the abbreviations section. 105 /// 106 /// This function currently checks that: 107 /// --No abbreviation declaration has more than one attributes with the same 108 /// name. 109 /// 110 /// \param Abbrev Pointer to the abbreviations section we are verifying 111 /// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo. 112 /// 113 /// \returns The number of errors that occurred during verification. 114 unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev); 115 116 /// Verifies the header of a unit in the .debug_info section. 117 /// 118 /// This function currently checks for: 119 /// - Unit is in 32-bit DWARF format. The function can be modified to 120 /// support 64-bit format. 121 /// - The DWARF version is valid 122 /// - The unit type is valid (if unit is in version >=5) 123 /// - The unit doesn't extend beyond .debug_info section 124 /// - The address size is valid 125 /// - The offset in the .debug_abbrev section is valid 126 /// 127 /// \param DebugInfoData The .debug_info section data 128 /// \param Offset A reference to the offset start of the unit. The offset will 129 /// be updated to point to the next unit in .debug_info 130 /// \param UnitIndex The index of the unit to be verified 131 /// \param UnitType A reference to the type of the unit 132 /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is 133 /// in 64-bit format. 134 /// 135 /// \returns true if the header is verified successfully, false otherwise. 136 bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData, 137 uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType, 138 bool &isUnitDWARF64); 139 140 /// Verifies the header of a unit in the .debug_info section. 141 /// 142 /// This function currently verifies: 143 /// - The debug info attributes. 144 /// - The debug info form=s. 145 /// - The presence of a root DIE. 146 /// - That the root DIE is a unit DIE. 147 /// - If a unit type is provided, that the unit DIE matches the unit type. 148 /// - The DIE ranges. 149 /// 150 /// \param Unit The DWARF Unit to verifiy. 151 /// \param UnitType An optional unit type which will be used to verify the 152 /// type of the unit DIE. 153 /// 154 /// \returns true if the content is verified successfully, false otherwise. 155 bool verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType = 0); 156 157 /// Verify that all Die ranges are valid. 158 /// 159 /// This function currently checks for: 160 /// - cases in which lowPC >= highPC 161 /// 162 /// \returns Number of errors that occurred during verification. 163 unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI); 164 165 /// Verifies the attribute's DWARF attribute and its value. 166 /// 167 /// This function currently checks for: 168 /// - DW_AT_ranges values is a valid .debug_ranges offset 169 /// - DW_AT_stmt_list is a valid .debug_line offset 170 /// 171 /// \param Die The DWARF DIE that owns the attribute value 172 /// \param AttrValue The DWARF attribute value to check 173 /// 174 /// \returns NumErrors The number of errors occurred during verification of 175 /// attributes' values in a .debug_info section unit 176 unsigned verifyDebugInfoAttribute(const DWARFDie &Die, 177 DWARFAttribute &AttrValue); 178 179 /// Verifies the attribute's DWARF form. 180 /// 181 /// This function currently checks for: 182 /// - All DW_FORM_ref values that are CU relative have valid CU offsets 183 /// - All DW_FORM_ref_addr values have valid .debug_info offsets 184 /// - All DW_FORM_strp values have valid .debug_str offsets 185 /// 186 /// \param Die The DWARF DIE that owns the attribute value 187 /// \param AttrValue The DWARF attribute value to check 188 /// 189 /// \returns NumErrors The number of errors occurred during verification of 190 /// attributes' forms in a .debug_info section unit 191 unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue); 192 193 /// Verifies the all valid references that were found when iterating through 194 /// all of the DIE attributes. 195 /// 196 /// This function will verify that all references point to DIEs whose DIE 197 /// offset matches. This helps to ensure if a DWARF link phase moved things 198 /// around, that it doesn't create invalid references by failing to relocate 199 /// CU relative and absolute references. 200 /// 201 /// \returns NumErrors The number of errors occurred during verification of 202 /// references for the .debug_info section 203 unsigned verifyDebugInfoReferences(); 204 205 /// Verify the DW_AT_stmt_list encoding and value and ensure that no 206 /// compile units that have the same DW_AT_stmt_list value. 207 void verifyDebugLineStmtOffsets(); 208 209 /// Verify that all of the rows in the line table are valid. 210 /// 211 /// This function currently checks for: 212 /// - addresses within a sequence that decrease in value 213 /// - invalid file indexes 214 void verifyDebugLineRows(); 215 216 /// Verify that an Apple-style accelerator table is valid. 217 /// 218 /// This function currently checks that: 219 /// - The fixed part of the header fits in the section 220 /// - The size of the section is as large as what the header describes 221 /// - There is at least one atom 222 /// - The form for each atom is valid 223 /// - The tag for each DIE in the table is valid 224 /// - The buckets have a valid index, or they are empty 225 /// - Each hashdata offset is valid 226 /// - Each DIE is valid 227 /// 228 /// \param AccelSection pointer to the section containing the acceleration table 229 /// \param StrData pointer to the string section 230 /// \param SectionName the name of the table we're verifying 231 /// 232 /// \returns The number of errors occurred during verification 233 unsigned verifyAppleAccelTable(const DWARFSection *AccelSection, 234 DataExtractor *StrData, 235 const char *SectionName); 236 237 unsigned verifyDebugNamesCULists(const DWARFDebugNames &AccelTable); 238 unsigned verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI, 239 const DataExtractor &StrData); 240 unsigned verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI); 241 unsigned verifyNameIndexAttribute(const DWARFDebugNames::NameIndex &NI, 242 const DWARFDebugNames::Abbrev &Abbr, 243 DWARFDebugNames::AttributeEncoding AttrEnc); 244 unsigned verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI, 245 const DWARFDebugNames::NameTableEntry &NTE); 246 unsigned verifyNameIndexCompleteness(const DWARFDie &Die, 247 const DWARFDebugNames::NameIndex &NI); 248 249 /// Verify that the DWARF v5 accelerator table is valid. 250 /// 251 /// This function currently checks that: 252 /// - Headers individual Name Indices fit into the section and can be parsed. 253 /// - Abbreviation tables can be parsed and contain valid index attributes 254 /// with correct form encodings. 255 /// - The CU lists reference existing compile units. 256 /// - The buckets have a valid index, or they are empty. 257 /// - All names are reachable via the hash table (they have the correct hash, 258 /// and the hash is in the correct bucket). 259 /// - Information in the index entries is complete (all required entries are 260 /// present) and consistent with the debug_info section DIEs. 261 /// 262 /// \param AccelSection section containing the acceleration table 263 /// \param StrData string section 264 /// 265 /// \returns The number of errors occurred during verification 266 unsigned verifyDebugNames(const DWARFSection &AccelSection, 267 const DataExtractor &StrData); 268 269 public: 270 DWARFVerifier(raw_ostream &S, DWARFContext &D, 271 DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE()) OS(S)272 : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)) {} 273 /// Verify the information in any of the following sections, if available: 274 /// .debug_abbrev, debug_abbrev.dwo 275 /// 276 /// Any errors are reported to the stream that was this object was 277 /// constructed with. 278 /// 279 /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully, 280 /// false otherwise. 281 bool handleDebugAbbrev(); 282 283 /// Verify the information in the .debug_info section. 284 /// 285 /// Any errors are reported to the stream that was this object was 286 /// constructed with. 287 /// 288 /// \returns true if the .debug_info verifies successfully, false otherwise. 289 bool handleDebugInfo(); 290 291 /// Verify the information in the .debug_line section. 292 /// 293 /// Any errors are reported to the stream that was this object was 294 /// constructed with. 295 /// 296 /// \returns true if the .debug_line verifies successfully, false otherwise. 297 bool handleDebugLine(); 298 299 /// Verify the information in accelerator tables, if they exist. 300 /// 301 /// Any errors are reported to the stream that was this object was 302 /// constructed with. 303 /// 304 /// \returns true if the existing Apple-style accelerator tables verify 305 /// successfully, false otherwise. 306 bool handleAccelTables(); 307 }; 308 309 static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS, 310 const DWARFVerifier::DieRangeInfo &RHS) { 311 return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die); 312 } 313 314 } // end namespace llvm 315 316 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H 317