Home | History | Annotate | Download | only in DWARF
      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 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   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           return LHS < RHS->getNextUnitOffset();
     86         });
     87     if (CU != this->end() && (*CU)->getOffset() <= Offset)
     88       return CU->get();
     89     return nullptr;
     90   }
     91   UnitType *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) override {
     92     const auto *CUOff = E.getOffset(DW_SECT_INFO);
     93     if (!CUOff)
     94       return nullptr;
     95 
     96     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           return LHS < RHS->getNextUnitOffset();
    102         });
    103     if (CU != this->end() && (*CU)->getOffset() <= Offset)
    104       return CU->get();
    105 
    106     if (!Parser)
    107       return nullptr;
    108 
    109     auto U = Parser(Offset);
    110     if (!U)
    111       U = nullptr;
    112 
    113     auto *NewCU = U.get();
    114     this->insert(CU, std::move(U));
    115     return NewCU;
    116   }
    117 
    118 private:
    119   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     if (Parsed)
    125       return;
    126     DataExtractor Data(Section.Data, LE, 0);
    127     if (!Parser) {
    128       const DWARFUnitIndex *Index = nullptr;
    129       if (IsDWO)
    130         Index = &getDWARFUnitIndex(Context, UnitType::Section);
    131       Parser = [=, &Context, &Section, &SOS,
    132                 &LS](uint32_t Offset) -> std::unique_ptr<UnitType> {
    133         if (!Data.isValidOffset(Offset))
    134           return nullptr;
    135         auto U = llvm::make_unique<UnitType>(
    136             Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, *this,
    137             Index ? Index->getFromOffset(Offset) : nullptr);
    138         if (!U->extract(Data, &Offset))
    139           return nullptr;
    140         return U;
    141       };
    142     }
    143     if (Lazy)
    144       return;
    145     auto I = this->begin();
    146     uint32_t Offset = 0;
    147     while (Data.isValidOffset(Offset)) {
    148       if (I != this->end() && (*I)->getOffset() == Offset) {
    149         ++I;
    150         continue;
    151       }
    152       auto U = Parser(Offset);
    153       if (!U)
    154         break;
    155       Offset = U->getNextUnitOffset();
    156       I = std::next(this->insert(I, std::move(U)));
    157     }
    158     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 class DWARFUnit {
    169   DWARFContext &Context;
    170   /// Section containing this DWARFUnit.
    171   const DWARFSection &InfoSection;
    172 
    173   const DWARFDebugAbbrev *Abbrev;
    174   const DWARFSection *RangeSection;
    175   uint32_t RangeSectionBase;
    176   const DWARFSection &LineSection;
    177   StringRef StringSection;
    178   const DWARFSection &StringOffsetSection;
    179   uint64_t StringOffsetSectionBase = 0;
    180   const DWARFSection *AddrOffsetSection;
    181   uint32_t AddrOffsetSectionBase = 0;
    182   bool isLittleEndian;
    183   bool isDWO;
    184   const DWARFUnitSectionBase &UnitSection;
    185 
    186   // Version, address size, and DWARF format.
    187   DWARFFormParams FormParams;
    188 
    189   uint32_t Offset;
    190   uint32_t Length;
    191   mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
    192   uint64_t AbbrOffset;
    193   uint8_t UnitType;
    194   llvm::Optional<BaseAddress> BaseAddr;
    195   /// The compile unit debug information entry items.
    196   std::vector<DWARFDebugInfoEntry> DieArray;
    197 
    198   /// Map from range's start address to end address and corresponding DIE.
    199   /// IntervalMap does not support range removal, as a result, we use the
    200   /// std::map::upper_bound for address range lookup.
    201   std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
    202 
    203   using die_iterator_range =
    204       iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>;
    205 
    206   std::shared_ptr<DWARFUnit> DWO;
    207 
    208   const DWARFUnitIndex::Entry *IndexEntry;
    209 
    210   uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) {
    211     auto First = DieArray.data();
    212     assert(Die >= First && Die < First + DieArray.size());
    213     return Die - First;
    214   }
    215 
    216 protected:
    217   virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
    218 
    219   /// Size in bytes of the unit header.
    220   virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; }
    221 
    222 public:
    223   DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
    224             const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS,
    225             const DWARFSection &SOS, const DWARFSection *AOS,
    226             const DWARFSection &LS, bool LE, bool IsDWO,
    227             const DWARFUnitSectionBase &UnitSection,
    228             const DWARFUnitIndex::Entry *IndexEntry = nullptr);
    229 
    230   virtual ~DWARFUnit();
    231 
    232   DWARFContext& getContext() const { return Context; }
    233 
    234   const DWARFSection &getLineSection() const { return LineSection; }
    235   StringRef getStringSection() const { return StringSection; }
    236   const DWARFSection &getStringOffsetSection() const {
    237     return StringOffsetSection;
    238   }
    239 
    240   void setAddrOffsetSection(const DWARFSection *AOS, uint32_t Base) {
    241     AddrOffsetSection = AOS;
    242     AddrOffsetSectionBase = Base;
    243   }
    244 
    245   /// Recursively update address to Die map.
    246   void updateAddressDieMap(DWARFDie Die);
    247 
    248   void setRangesSection(const DWARFSection *RS, uint32_t Base) {
    249     RangeSection = RS;
    250     RangeSectionBase = Base;
    251   }
    252 
    253   bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
    254   bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
    255 
    256   DWARFDataExtractor getDebugInfoExtractor() const;
    257 
    258   DataExtractor getStringExtractor() const {
    259     return DataExtractor(StringSection, false, 0);
    260   }
    261 
    262 
    263   bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
    264 
    265   /// extractRangeList - extracts the range list referenced by this compile
    266   /// unit from .debug_ranges section. Returns true on success.
    267   /// Requires that compile unit is already extracted.
    268   bool extractRangeList(uint32_t RangeListOffset,
    269                         DWARFDebugRangeList &RangeList) const;
    270   void clear();
    271   uint32_t getOffset() const { return Offset; }
    272   uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
    273   uint32_t getLength() const { return Length; }
    274 
    275   const DWARFFormParams &getFormParams() const { return FormParams; }
    276   uint16_t getVersion() const { return FormParams.Version; }
    277   dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
    278   uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
    279   uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
    280   uint8_t getDwarfOffsetByteSize() const {
    281     return FormParams.getDwarfOffsetByteSize();
    282   }
    283 
    284   const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
    285 
    286   uint8_t getUnitType() const { return UnitType; }
    287 
    288   static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
    289     switch (UnitType) {
    290     case dwarf::DW_UT_compile:
    291       return Tag == dwarf::DW_TAG_compile_unit;
    292     case dwarf::DW_UT_type:
    293       return Tag == dwarf::DW_TAG_type_unit;
    294     case dwarf::DW_UT_partial:
    295       return Tag == dwarf::DW_TAG_partial_unit;
    296     case dwarf::DW_UT_skeleton:
    297       return Tag == dwarf::DW_TAG_skeleton_unit;
    298     case dwarf::DW_UT_split_compile:
    299     case dwarf::DW_UT_split_type:
    300       return dwarf::isUnitType(Tag);
    301     }
    302     return false;
    303   }
    304 
    305   /// \brief Return the number of bytes for the header of a unit of
    306   /// UnitType type.
    307   ///
    308   /// This function must be called with a valid unit type which in
    309   /// DWARF5 is defined as one of the following six types.
    310   static uint32_t getDWARF5HeaderSize(uint8_t UnitType) {
    311     switch (UnitType) {
    312     case dwarf::DW_UT_compile:
    313     case dwarf::DW_UT_partial:
    314       return 12;
    315     case dwarf::DW_UT_skeleton:
    316     case dwarf::DW_UT_split_compile:
    317       return 20;
    318     case dwarf::DW_UT_type:
    319     case dwarf::DW_UT_split_type:
    320       return 24;
    321     }
    322     llvm_unreachable("Invalid UnitType.");
    323   }
    324 
    325   llvm::Optional<BaseAddress> getBaseAddress() const { return BaseAddr; }
    326 
    327   void setBaseAddress(BaseAddress BaseAddr) { this->BaseAddr = BaseAddr; }
    328 
    329   DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
    330     extractDIEsIfNeeded(ExtractUnitDIEOnly);
    331     if (DieArray.empty())
    332       return DWARFDie();
    333     return DWARFDie(this, &DieArray[0]);
    334   }
    335 
    336   const char *getCompilationDir();
    337   Optional<uint64_t> getDWOId();
    338 
    339   void collectAddressRanges(DWARFAddressRangesVector &CURanges);
    340 
    341   /// getInlinedChainForAddress - fetches inlined chain for a given address.
    342   /// Returns empty chain if there is no subprogram containing address. The
    343   /// chain is valid as long as parsed compile unit DIEs are not cleared.
    344   void getInlinedChainForAddress(uint64_t Address,
    345                                  SmallVectorImpl<DWARFDie> &InlinedChain);
    346 
    347   /// getUnitSection - Return the DWARFUnitSection containing this unit.
    348   const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; }
    349 
    350   /// \brief Returns the number of DIEs in the unit. Parses the unit
    351   /// if necessary.
    352   unsigned getNumDIEs() {
    353     extractDIEsIfNeeded(false);
    354     return DieArray.size();
    355   }
    356 
    357   /// \brief Return the index of a DIE inside the unit's DIE vector.
    358   ///
    359   /// It is illegal to call this method with a DIE that hasn't be
    360   /// created by this unit. In other word, it's illegal to call this
    361   /// method on a DIE that isn't accessible by following
    362   /// children/sibling links starting from this unit's getUnitDIE().
    363   uint32_t getDIEIndex(const DWARFDie &D) {
    364     return getDIEIndex(D.getDebugInfoEntry());
    365   }
    366 
    367   /// \brief Return the DIE object at the given index.
    368   DWARFDie getDIEAtIndex(unsigned Index) {
    369     assert(Index < DieArray.size());
    370     return DWARFDie(this, &DieArray[Index]);
    371   }
    372 
    373   DWARFDie getParent(const DWARFDebugInfoEntry *Die);
    374   DWARFDie getSibling(const DWARFDebugInfoEntry *Die);
    375 
    376   /// \brief Return the DIE object for a given offset inside the
    377   /// unit's DIE vector.
    378   ///
    379   /// The unit needs to have its DIEs extracted for this method to work.
    380   DWARFDie getDIEForOffset(uint32_t Offset) {
    381     extractDIEsIfNeeded(false);
    382     assert(!DieArray.empty());
    383     auto it = std::lower_bound(
    384         DieArray.begin(), DieArray.end(), Offset,
    385         [](const DWARFDebugInfoEntry &LHS, uint32_t Offset) {
    386           return LHS.getOffset() < Offset;
    387         });
    388     if (it != DieArray.end() && it->getOffset() == Offset)
    389       return DWARFDie(this, &*it);
    390     return DWARFDie();
    391   }
    392 
    393   uint32_t getLineTableOffset() const {
    394     if (IndexEntry)
    395       if (const auto *Contrib = IndexEntry->getOffset(DW_SECT_LINE))
    396         return Contrib->Offset;
    397     return 0;
    398   }
    399 
    400   die_iterator_range dies() {
    401     extractDIEsIfNeeded(false);
    402     return die_iterator_range(DieArray.begin(), DieArray.end());
    403   }
    404 
    405 private:
    406   /// Size in bytes of the .debug_info data associated with this compile unit.
    407   size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); }
    408 
    409   /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
    410   /// hasn't already been done. Returns the number of DIEs parsed at this call.
    411   size_t extractDIEsIfNeeded(bool CUDieOnly);
    412 
    413   /// extractDIEsToVector - Appends all parsed DIEs to a vector.
    414   void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
    415                            std::vector<DWARFDebugInfoEntry> &DIEs) const;
    416 
    417   /// clearDIEs - Clear parsed DIEs to keep memory usage low.
    418   void clearDIEs(bool KeepCUDie);
    419 
    420   /// parseDWO - Parses .dwo file for current compile unit. Returns true if
    421   /// it was actually constructed.
    422   bool parseDWO();
    423 
    424   /// getSubroutineForAddress - Returns subprogram DIE with address range
    425   /// encompassing the provided address. The pointer is alive as long as parsed
    426   /// compile unit DIEs are not cleared.
    427   DWARFDie getSubroutineForAddress(uint64_t Address);
    428 };
    429 
    430 } // end namespace llvm
    431 
    432 #endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
    433