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