LCOV - code coverage report
Current view: top level - include/llvm/DebugInfo/DWARF - DWARFVerifier.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 10 10 100.0 %
Date: 2018-07-13 00:08:38 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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        2204 :   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;
      48         400 :     DieRangeInfo(DWARFDie Die) : Die(Die) {}
      49             : 
      50             :     /// Used for unit testing.
      51             :     DieRangeInfo(std::vector<DWARFAddressRange> Ranges)
      52          32 :         : 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.
      66         316 :     address_range_iterator findRange(const DWARFAddressRange &R) const {
      67         316 :       auto Begin = Ranges.begin();
      68         316 :       auto End = Ranges.end();
      69             :       auto Iter = std::upper_bound(Begin, End, R);
      70         316 :       if (Iter != Begin)
      71             :         --Iter;
      72         316 :       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 &note() 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())
     272         130 :       : 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        2949 :   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

Generated by: LCOV version 1.13