LCOV - code coverage report
Current view: top level - include/llvm/DebugInfo/DWARF - DWARFUnit.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 68 79 86.1 %
Date: 2018-02-21 06:32:55 Functions: 15 17 88.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- DWARFUnit.h ----------------------------------------------*- C++ -*-===//
       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_DWARFUNIT_H
      11             : #define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
      12             : 
      13             : #include "llvm/ADT/Optional.h"
      14             : #include "llvm/ADT/STLExtras.h"
      15             : #include "llvm/ADT/SmallVector.h"
      16             : #include "llvm/ADT/StringRef.h"
      17             : #include "llvm/ADT/iterator_range.h"
      18             : #include "llvm/BinaryFormat/Dwarf.h"
      19             : #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
      20             : #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
      21             : #include "llvm/DebugInfo/DWARF/DWARFDie.h"
      22             : #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
      23             : #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
      24             : #include "llvm/DebugInfo/DWARF/DWARFSection.h"
      25             : #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
      26             : #include "llvm/Support/DataExtractor.h"
      27             : #include <algorithm>
      28             : #include <cassert>
      29             : #include <cstddef>
      30             : #include <cstdint>
      31             : #include <map>
      32             : #include <memory>
      33             : #include <utility>
      34             : #include <vector>
      35             : 
      36             : namespace llvm {
      37             : 
      38             : class DWARFAbbreviationDeclarationSet;
      39             : class DWARFContext;
      40             : class DWARFDebugAbbrev;
      41             : class DWARFUnit;
      42             : 
      43             : /// Base class for all DWARFUnitSection classes. This provides the
      44             : /// functionality common to all unit types.
      45             : class DWARFUnitSectionBase {
      46             : public:
      47             :   /// Returns the Unit that contains the given section offset in the
      48             :   /// same section this Unit originated from.
      49             :   virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0;
      50             :   virtual DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) = 0;
      51             : 
      52             :   void parse(DWARFContext &C, const DWARFSection &Section);
      53             :   void parseDWO(DWARFContext &C, const DWARFSection &DWOSection,
      54             :                 bool Lazy = false);
      55             : 
      56             : protected:
      57             :   ~DWARFUnitSectionBase() = default;
      58             : 
      59             :   virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
      60             :                          const DWARFDebugAbbrev *DA, const DWARFSection *RS,
      61             :                          StringRef SS, const DWARFSection &SOS,
      62             :                          const DWARFSection *AOS, const DWARFSection &LS,
      63             :                          bool isLittleEndian, bool isDWO, bool Lazy) = 0;
      64             : };
      65             : 
      66             : const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
      67             :                                         DWARFSectionKind Kind);
      68             : 
      69             : /// Concrete instance of DWARFUnitSection, specialized for one Unit type.
      70             : template<typename UnitType>
      71        8093 : class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
      72             :                                public DWARFUnitSectionBase {
      73             :   bool Parsed = false;
      74             :   std::function<std::unique_ptr<UnitType>(uint32_t)> Parser;
      75             : 
      76             : public:
      77             :   using UnitVector = SmallVectorImpl<std::unique_ptr<UnitType>>;
      78             :   using iterator = typename UnitVector::iterator;
      79             :   using iterator_range = llvm::iterator_range<typename UnitVector::iterator>;
      80             : 
      81        5598 :   UnitType *getUnitForOffset(uint32_t Offset) const override {
      82             :     auto *CU = std::upper_bound(
      83             :         this->begin(), this->end(), Offset,
      84             :         [](uint32_t LHS, const std::unique_ptr<UnitType> &RHS) {
      85        9894 :           return LHS < RHS->getNextUnitOffset();
      86             :         });
      87       10825 :     if (CU != this->end() && (*CU)->getOffset() <= Offset)
      88             :       return CU->get();
      89             :     return nullptr;
      90             :   }
      91           4 :   UnitType *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) override {
      92           4 :     const auto *CUOff = E.getOffset(DW_SECT_INFO);
      93           4 :     if (!CUOff)
      94             :       return nullptr;
      95             : 
      96           4 :     auto Offset = CUOff->Offset;
      97             : 
      98             :     auto *CU = std::upper_bound(
      99             :         this->begin(), this->end(), CUOff->Offset,
     100             :         [](uint32_t LHS, const std::unique_ptr<UnitType> &RHS) {
     101           0 :           return LHS < RHS->getNextUnitOffset();
     102             :         });
     103           4 :     if (CU != this->end() && (*CU)->getOffset() <= Offset)
     104             :       return CU->get();
     105             : 
     106           4 :     if (!Parser)
     107             :       return nullptr;
     108             : 
     109             :     auto U = Parser(Offset);
     110           4 :     if (!U)
     111             :       U = nullptr;
     112             : 
     113             :     auto *NewCU = U.get();
     114           4 :     this->insert(CU, std::move(U));
     115             :     return NewCU;
     116             :   }
     117             : 
     118             : private:
     119        3813 :   void parseImpl(DWARFContext &Context, const DWARFSection &Section,
     120             :                  const DWARFDebugAbbrev *DA, const DWARFSection *RS,
     121             :                  StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
     122             :                  const DWARFSection &LS, bool LE, bool IsDWO,
     123             :                  bool Lazy) override {
     124        3813 :     if (Parsed)
     125             :       return;
     126             :     DataExtractor Data(Section.Data, LE, 0);
     127        1953 :     if (!Parser) {
     128             :       const DWARFUnitIndex *Index = nullptr;
     129        1938 :       if (IsDWO)
     130         650 :         Index = &getDWARFUnitIndex(Context, UnitType::Section);
     131        1938 :       Parser = [=, &Context, &Section, &SOS,
     132       13029 :                 &LS](uint32_t Offset) -> std::unique_ptr<UnitType> {
     133        8686 :         if (!Data.isValidOffset(Offset))
     134             :           return nullptr;
     135       13029 :         auto U = llvm::make_unique<UnitType>(
     136        4343 :             Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, *this,
     137        4343 :             Index ? Index->getFromOffset(Offset) : nullptr);
     138        4343 :         if (!U->extract(Data, &Offset))
     139             :           return nullptr;
     140             :         return U;
     141             :       };
     142             :     }
     143        1953 :     if (Lazy)
     144             :       return;
     145             :     auto I = this->begin();
     146             :     uint32_t Offset = 0;
     147        6251 :     while (Data.isValidOffset(Offset)) {
     148        4339 :       if (I != this->end() && (*I)->getOffset() == Offset) {
     149           0 :         ++I;
     150           0 :         continue;
     151             :       }
     152             :       auto U = Parser(Offset);
     153        4339 :       if (!U)
     154             :         break;
     155        4317 :       Offset = U->getNextUnitOffset();
     156        4317 :       I = std::next(this->insert(I, std::move(U)));
     157             :     }
     158        1934 :     Parsed = true;
     159             :   }
     160             : };
     161             : 
     162             : /// Represents base address of the CU.
     163             : struct BaseAddress {
     164             :   uint64_t Address;
     165             :   uint64_t SectionIndex;
     166             : };
     167             : 
     168             : /// Represents a unit's contribution to the string offsets table.
     169             : struct StrOffsetsContributionDescriptor {
     170             :   uint64_t Base = 0;
     171             :   uint64_t Size = 0;
     172             :   /// Format and version.
     173             :   DWARFFormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
     174             : 
     175             :   StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size,
     176             :                                    uint8_t Version, dwarf::DwarfFormat Format)
     177             :       : Base(Base), Size(Size), FormParams({Version, 0, Format}) {}
     178             : 
     179             :   uint8_t getVersion() const { return FormParams.Version; }
     180             :   dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
     181             :   uint8_t getDwarfOffsetByteSize() const {
     182        1083 :     return FormParams.getDwarfOffsetByteSize();
     183             :   }
     184             :   /// Determine whether a contribution to the string offsets table is
     185             :   /// consistent with the relevant section size and that its length is
     186             :   /// a multiple of the size of one of its entries.
     187             :   Optional<StrOffsetsContributionDescriptor>
     188             :   validateContributionSize(DWARFDataExtractor &DA);
     189             : };
     190             : 
     191        9140 : class DWARFUnit {
     192             :   DWARFContext &Context;
     193             :   /// Section containing this DWARFUnit.
     194             :   const DWARFSection &InfoSection;
     195             : 
     196             :   const DWARFDebugAbbrev *Abbrev;
     197             :   const DWARFSection *RangeSection;
     198             :   uint32_t RangeSectionBase;
     199             :   const DWARFSection &LineSection;
     200             :   StringRef StringSection;
     201             :   const DWARFSection &StringOffsetSection;
     202             :   const DWARFSection *AddrOffsetSection;
     203             :   uint32_t AddrOffsetSectionBase = 0;
     204             :   bool isLittleEndian;
     205             :   bool isDWO;
     206             :   const DWARFUnitSectionBase &UnitSection;
     207             : 
     208             :   // Version, address size, and DWARF format.
     209             :   DWARFFormParams FormParams;
     210             :   /// Start, length, and DWARF format of the unit's contribution to the string
     211             :   /// offsets table (DWARF v5).
     212             :   Optional<StrOffsetsContributionDescriptor> StringOffsetsTableContribution;
     213             : 
     214             :   uint32_t Offset;
     215             :   uint32_t Length;
     216             :   mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
     217             :   uint64_t AbbrOffset;
     218             :   uint8_t UnitType;
     219             :   llvm::Optional<BaseAddress> BaseAddr;
     220             :   /// The compile unit debug information entry items.
     221             :   std::vector<DWARFDebugInfoEntry> DieArray;
     222             : 
     223             :   /// Map from range's start address to end address and corresponding DIE.
     224             :   /// IntervalMap does not support range removal, as a result, we use the
     225             :   /// std::map::upper_bound for address range lookup.
     226             :   std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
     227             : 
     228             :   using die_iterator_range =
     229             :       iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>;
     230             : 
     231             :   std::shared_ptr<DWARFUnit> DWO;
     232             : 
     233             :   const DWARFUnitIndex::Entry *IndexEntry;
     234             : 
     235             :   uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) {
     236       45110 :     auto First = DieArray.data();
     237             :     assert(Die >= First && Die < First + DieArray.size());
     238       45110 :     return Die - First;
     239             :   }
     240             : 
     241             : protected:
     242             :   virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
     243             : 
     244             :   /// Size in bytes of the unit header.
     245        5943 :   virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; }
     246             : 
     247             :   /// Find the unit's contribution to the string offsets table and determine its
     248             :   /// length and form. The given offset is expected to be derived from the unit
     249             :   /// DIE's DW_AT_str_offsets_base attribute.
     250             :   Optional<StrOffsetsContributionDescriptor>
     251             :   determineStringOffsetsTableContribution(DWARFDataExtractor &DA,
     252             :                                           uint64_t Offset);
     253             : 
     254             :   /// Find the unit's contribution to the string offsets table and determine its
     255             :   /// length and form. The given offset is expected to be 0 in a dwo file or,
     256             :   /// in a dwp file, the start of the unit's contribution to the string offsets
     257             :   /// table section (as determined by the index table).
     258             :   Optional<StrOffsetsContributionDescriptor>
     259             :   determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA,
     260             :                                              uint64_t Offset);
     261             : 
     262             : public:
     263             :   DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
     264             :             const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS,
     265             :             const DWARFSection &SOS, const DWARFSection *AOS,
     266             :             const DWARFSection &LS, bool LE, bool IsDWO,
     267             :             const DWARFUnitSectionBase &UnitSection,
     268             :             const DWARFUnitIndex::Entry *IndexEntry = nullptr);
     269             : 
     270             :   virtual ~DWARFUnit();
     271             : 
     272             :   DWARFContext& getContext() const { return Context; }
     273             : 
     274             :   const DWARFSection &getLineSection() const { return LineSection; }
     275             :   StringRef getStringSection() const { return StringSection; }
     276             :   const DWARFSection &getStringOffsetSection() const {
     277             :     return StringOffsetSection;
     278             :   }
     279             : 
     280             :   void setAddrOffsetSection(const DWARFSection *AOS, uint32_t Base) {
     281          19 :     AddrOffsetSection = AOS;
     282          19 :     AddrOffsetSectionBase = Base;
     283             :   }
     284             : 
     285             :   /// Recursively update address to Die map.
     286             :   void updateAddressDieMap(DWARFDie Die);
     287             : 
     288             :   void setRangesSection(const DWARFSection *RS, uint32_t Base) {
     289          19 :     RangeSection = RS;
     290          19 :     RangeSectionBase = Base;
     291             :   }
     292             : 
     293             :   bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
     294             :   bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
     295             : 
     296             :   DWARFDataExtractor getDebugInfoExtractor() const;
     297             : 
     298             :   DataExtractor getStringExtractor() const {
     299             :     return DataExtractor(StringSection, false, 0);
     300             :   }
     301             : 
     302             :   bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
     303             : 
     304             :   /// extractRangeList - extracts the range list referenced by this compile
     305             :   /// unit from .debug_ranges section. Returns true on success.
     306             :   /// Requires that compile unit is already extracted.
     307             :   bool extractRangeList(uint32_t RangeListOffset,
     308             :                         DWARFDebugRangeList &RangeList) const;
     309             :   void clear();
     310             :   uint32_t getOffset() const { return Offset; }
     311       26103 :   uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
     312             :   uint32_t getLength() const { return Length; }
     313             : 
     314             :   const Optional<StrOffsetsContributionDescriptor> &
     315             :   getStringOffsetsTableContribution() const {
     316          38 :     return StringOffsetsTableContribution;
     317             :   }
     318       85140 :   const DWARFFormParams &getFormParams() const { return FormParams; }
     319             :   uint16_t getVersion() const { return FormParams.Version; }
     320             :   dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
     321             :   uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
     322             :   uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
     323             :   uint8_t getDwarfOffsetByteSize() const {
     324       11469 :     return FormParams.getDwarfOffsetByteSize();
     325             :   }
     326             : 
     327             :   uint8_t getDwarfStringOffsetsByteSize() const {
     328             :     assert(StringOffsetsTableContribution);
     329             :     return StringOffsetsTableContribution->getDwarfOffsetByteSize();
     330             :   }
     331             : 
     332             :   uint64_t getStringOffsetsBase() const {
     333             :     assert(StringOffsetsTableContribution);
     334        1024 :     return StringOffsetsTableContribution->Base;
     335             :   }
     336             : 
     337             :   const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
     338             : 
     339             :   uint8_t getUnitType() const { return UnitType; }
     340             : 
     341           4 :   static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
     342           4 :     switch (UnitType) {
     343           4 :     case dwarf::DW_UT_compile:
     344           4 :       return Tag == dwarf::DW_TAG_compile_unit;
     345           0 :     case dwarf::DW_UT_type:
     346           0 :       return Tag == dwarf::DW_TAG_type_unit;
     347           0 :     case dwarf::DW_UT_partial:
     348           0 :       return Tag == dwarf::DW_TAG_partial_unit;
     349           0 :     case dwarf::DW_UT_skeleton:
     350           0 :       return Tag == dwarf::DW_TAG_skeleton_unit;
     351           0 :     case dwarf::DW_UT_split_compile:
     352             :     case dwarf::DW_UT_split_type:
     353             :       return dwarf::isUnitType(Tag);
     354             :     }
     355             :     return false;
     356             :   }
     357             : 
     358             :   /// \brief Return the number of bytes for the header of a unit of
     359             :   /// UnitType type.
     360             :   ///
     361             :   /// This function must be called with a valid unit type which in
     362             :   /// DWARF5 is defined as one of the following six types.
     363             :   static uint32_t getDWARF5HeaderSize(uint8_t UnitType) {
     364             :     switch (UnitType) {
     365             :     case dwarf::DW_UT_compile:
     366             :     case dwarf::DW_UT_partial:
     367             :       return 12;
     368             :     case dwarf::DW_UT_skeleton:
     369             :     case dwarf::DW_UT_split_compile:
     370             :       return 20;
     371             :     case dwarf::DW_UT_type:
     372             :     case dwarf::DW_UT_split_type:
     373             :       return 24;
     374             :     }
     375             :     llvm_unreachable("Invalid UnitType.");
     376             :   }
     377             : 
     378             :   llvm::Optional<BaseAddress> getBaseAddress() const { return BaseAddr; }
     379             : 
     380             :   void setBaseAddress(BaseAddress BaseAddr) { this->BaseAddr = BaseAddr; }
     381             : 
     382        3470 :   DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
     383       18213 :     extractDIEsIfNeeded(ExtractUnitDIEOnly);
     384       18213 :     if (DieArray.empty())
     385           0 :       return DWARFDie();
     386        3470 :     return DWARFDie(this, &DieArray[0]);
     387             :   }
     388             : 
     389             :   const char *getCompilationDir();
     390             :   Optional<uint64_t> getDWOId();
     391             : 
     392             :   void collectAddressRanges(DWARFAddressRangesVector &CURanges);
     393             : 
     394             :   /// Returns subprogram DIE with address range encompassing the provided
     395             :   /// address. The pointer is alive as long as parsed compile unit DIEs are not
     396             :   /// cleared.
     397             :   DWARFDie getSubroutineForAddress(uint64_t Address);
     398             : 
     399             :   /// getInlinedChainForAddress - fetches inlined chain for a given address.
     400             :   /// Returns empty chain if there is no subprogram containing address. The
     401             :   /// chain is valid as long as parsed compile unit DIEs are not cleared.
     402             :   void getInlinedChainForAddress(uint64_t Address,
     403             :                                  SmallVectorImpl<DWARFDie> &InlinedChain);
     404             : 
     405             :   /// getUnitSection - Return the DWARFUnitSection containing this unit.
     406             :   const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; }
     407             : 
     408             :   /// \brief Returns the number of DIEs in the unit. Parses the unit
     409             :   /// if necessary.
     410             :   unsigned getNumDIEs() {
     411        1715 :     extractDIEsIfNeeded(false);
     412        3226 :     return DieArray.size();
     413             :   }
     414             : 
     415             :   /// \brief Return the index of a DIE inside the unit's DIE vector.
     416             :   ///
     417             :   /// It is illegal to call this method with a DIE that hasn't be
     418             :   /// created by this unit. In other word, it's illegal to call this
     419             :   /// method on a DIE that isn't accessible by following
     420             :   /// children/sibling links starting from this unit's getUnitDIE().
     421             :   uint32_t getDIEIndex(const DWARFDie &D) {
     422        6511 :     return getDIEIndex(D.getDebugInfoEntry());
     423             :   }
     424             : 
     425             :   /// \brief Return the DIE object at the given index.
     426             :   DWARFDie getDIEAtIndex(unsigned Index) {
     427             :     assert(Index < DieArray.size());
     428        2395 :     return DWARFDie(this, &DieArray[Index]);
     429             :   }
     430             : 
     431             :   DWARFDie getParent(const DWARFDebugInfoEntry *Die);
     432             :   DWARFDie getSibling(const DWARFDebugInfoEntry *Die);
     433             :   DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die);
     434             : 
     435             :   /// \brief Return the DIE object for a given offset inside the
     436             :   /// unit's DIE vector.
     437             :   ///
     438             :   /// The unit needs to have its DIEs extracted for this method to work.
     439        6484 :   DWARFDie getDIEForOffset(uint32_t Offset) {
     440        6484 :     extractDIEsIfNeeded(false);
     441             :     assert(!DieArray.empty());
     442             :     auto it = std::lower_bound(
     443             :         DieArray.begin(), DieArray.end(), Offset,
     444             :         [](const DWARFDebugInfoEntry &LHS, uint32_t Offset) {
     445       28193 :           return LHS.getOffset() < Offset;
     446             :         });
     447        6484 :     if (it != DieArray.end() && it->getOffset() == Offset)
     448        6481 :       return DWARFDie(this, &*it);
     449           3 :     return DWARFDie();
     450             :   }
     451             : 
     452             :   uint32_t getLineTableOffset() const {
     453        3422 :     if (IndexEntry)
     454          10 :       if (const auto *Contrib = IndexEntry->getOffset(DW_SECT_LINE))
     455          10 :         return Contrib->Offset;
     456             :     return 0;
     457             :   }
     458             : 
     459             :   die_iterator_range dies() {
     460          35 :     extractDIEsIfNeeded(false);
     461             :     return die_iterator_range(DieArray.begin(), DieArray.end());
     462             :   }
     463             : 
     464             : private:
     465             :   /// Size in bytes of the .debug_info data associated with this compile unit.
     466        1766 :   size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); }
     467             : 
     468             :   /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
     469             :   /// hasn't already been done. Returns the number of DIEs parsed at this call.
     470             :   size_t extractDIEsIfNeeded(bool CUDieOnly);
     471             : 
     472             :   /// extractDIEsToVector - Appends all parsed DIEs to a vector.
     473             :   void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
     474             :                            std::vector<DWARFDebugInfoEntry> &DIEs) const;
     475             : 
     476             :   /// clearDIEs - Clear parsed DIEs to keep memory usage low.
     477             :   void clearDIEs(bool KeepCUDie);
     478             : 
     479             :   /// parseDWO - Parses .dwo file for current compile unit. Returns true if
     480             :   /// it was actually constructed.
     481             :   bool parseDWO();
     482             : };
     483             : 
     484             : } // end namespace llvm
     485             : 
     486             : #endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H

Generated by: LCOV version 1.13