Home | History | Annotate | Line # | Download | only in DWARF
      1 //===- DWARFDie.h -----------------------------------------------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #ifndef LLVM_DEBUGINFO_DWARF_DWARFDIE_H
     10 #define LLVM_DEBUGINFO_DWARF_DWARFDIE_H
     11 
     12 #include "llvm/ADT/ArrayRef.h"
     13 #include "llvm/ADT/Optional.h"
     14 #include "llvm/ADT/iterator.h"
     15 #include "llvm/ADT/iterator_range.h"
     16 #include "llvm/BinaryFormat/Dwarf.h"
     17 #include "llvm/DebugInfo/DIContext.h"
     18 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
     19 #include "llvm/DebugInfo/DWARF/DWARFAttribute.h"
     20 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
     21 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
     22 #include <cassert>
     23 #include <cstdint>
     24 #include <iterator>
     25 
     26 namespace llvm {
     27 
     28 class DWARFUnit;
     29 class raw_ostream;
     30 
     31 //===----------------------------------------------------------------------===//
     32 /// Utility class that carries the DWARF compile/type unit and the debug info
     33 /// entry in an object.
     34 ///
     35 /// When accessing information from a debug info entry we always need to DWARF
     36 /// compile/type unit in order to extract the info correctly as some information
     37 /// is relative to the compile/type unit. Prior to this class the DWARFUnit and
     38 /// the DWARFDebugInfoEntry was passed around separately and there was the
     39 /// possibility for error if the wrong DWARFUnit was used to extract a unit
     40 /// relative offset. This class helps to ensure that this doesn't happen and
     41 /// also simplifies the attribute extraction calls by not having to specify the
     42 /// DWARFUnit for each call.
     43 class DWARFDie {
     44   DWARFUnit *U = nullptr;
     45   const DWARFDebugInfoEntry *Die = nullptr;
     46 
     47 public:
     48   DWARFDie() = default;
     49   DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry *D) : U(Unit), Die(D) {}
     50 
     51   bool isValid() const { return U && Die; }
     52   explicit operator bool() const { return isValid(); }
     53   const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; }
     54   DWARFUnit *getDwarfUnit() const { return U; }
     55 
     56   /// Get the abbreviation declaration for this DIE.
     57   ///
     58   /// \returns the abbreviation declaration or NULL for null tags.
     59   const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {
     60     assert(isValid() && "must check validity prior to calling");
     61     return Die->getAbbreviationDeclarationPtr();
     62   }
     63 
     64   /// Get the absolute offset into the debug info or types section.
     65   ///
     66   /// \returns the DIE offset or -1U if invalid.
     67   uint64_t getOffset() const {
     68     assert(isValid() && "must check validity prior to calling");
     69     return Die->getOffset();
     70   }
     71 
     72   dwarf::Tag getTag() const {
     73     auto AbbrevDecl = getAbbreviationDeclarationPtr();
     74     if (AbbrevDecl)
     75       return AbbrevDecl->getTag();
     76     return dwarf::DW_TAG_null;
     77   }
     78 
     79   bool hasChildren() const {
     80     assert(isValid() && "must check validity prior to calling");
     81     return Die->hasChildren();
     82   }
     83 
     84   /// Returns true for a valid DIE that terminates a sibling chain.
     85   bool isNULL() const { return getAbbreviationDeclarationPtr() == nullptr; }
     86 
     87   /// Returns true if DIE represents a subprogram (not inlined).
     88   bool isSubprogramDIE() const;
     89 
     90   /// Returns true if DIE represents a subprogram or an inlined subroutine.
     91   bool isSubroutineDIE() const;
     92 
     93   /// Get the parent of this DIE object.
     94   ///
     95   /// \returns a valid DWARFDie instance if this object has a parent or an
     96   /// invalid DWARFDie instance if it doesn't.
     97   DWARFDie getParent() const;
     98 
     99   /// Get the sibling of this DIE object.
    100   ///
    101   /// \returns a valid DWARFDie instance if this object has a sibling or an
    102   /// invalid DWARFDie instance if it doesn't.
    103   DWARFDie getSibling() const;
    104 
    105   /// Get the previous sibling of this DIE object.
    106   ///
    107   /// \returns a valid DWARFDie instance if this object has a sibling or an
    108   /// invalid DWARFDie instance if it doesn't.
    109   DWARFDie getPreviousSibling() const;
    110 
    111   /// Get the first child of this DIE object.
    112   ///
    113   /// \returns a valid DWARFDie instance if this object has children or an
    114   /// invalid DWARFDie instance if it doesn't.
    115   DWARFDie getFirstChild() const;
    116 
    117   /// Get the last child of this DIE object.
    118   ///
    119   /// \returns a valid null DWARFDie instance if this object has children or an
    120   /// invalid DWARFDie instance if it doesn't.
    121   DWARFDie getLastChild() const;
    122 
    123   /// Dump the DIE and all of its attributes to the supplied stream.
    124   ///
    125   /// \param OS the stream to use for output.
    126   /// \param indent the number of characters to indent each line that is output.
    127   void dump(raw_ostream &OS, unsigned indent = 0,
    128             DIDumpOptions DumpOpts = DIDumpOptions()) const;
    129 
    130   /// Convenience zero-argument overload for debugging.
    131   LLVM_DUMP_METHOD void dump() const;
    132 
    133   /// Extract the specified attribute from this DIE.
    134   ///
    135   /// Extract an attribute value from this DIE only. This call doesn't look
    136   /// for the attribute value in any DW_AT_specification or
    137   /// DW_AT_abstract_origin referenced DIEs.
    138   ///
    139   /// \param Attr the attribute to extract.
    140   /// \returns an optional DWARFFormValue that will have the form value if the
    141   /// attribute was successfully extracted.
    142   Optional<DWARFFormValue> find(dwarf::Attribute Attr) const;
    143 
    144   /// Extract the first value of any attribute in Attrs from this DIE.
    145   ///
    146   /// Extract the first attribute that matches from this DIE only. This call
    147   /// doesn't look for the attribute value in any DW_AT_specification or
    148   /// DW_AT_abstract_origin referenced DIEs. The attributes will be searched
    149   /// linearly in the order they are specified within Attrs.
    150   ///
    151   /// \param Attrs an array of DWARF attribute to look for.
    152   /// \returns an optional that has a valid DWARFFormValue for the first
    153   /// matching attribute in Attrs, or None if none of the attributes in Attrs
    154   /// exist in this DIE.
    155   Optional<DWARFFormValue> find(ArrayRef<dwarf::Attribute> Attrs) const;
    156 
    157   /// Extract the first value of any attribute in Attrs from this DIE and
    158   /// recurse into any DW_AT_specification or DW_AT_abstract_origin referenced
    159   /// DIEs.
    160   ///
    161   /// \param Attrs an array of DWARF attribute to look for.
    162   /// \returns an optional that has a valid DWARFFormValue for the first
    163   /// matching attribute in Attrs, or None if none of the attributes in Attrs
    164   /// exist in this DIE or in any DW_AT_specification or DW_AT_abstract_origin
    165   /// DIEs.
    166   Optional<DWARFFormValue>
    167   findRecursively(ArrayRef<dwarf::Attribute> Attrs) const;
    168 
    169   /// Extract the specified attribute from this DIE as the referenced DIE.
    170   ///
    171   /// Regardless of the reference type, return the correct DWARFDie instance if
    172   /// the attribute exists. The returned DWARFDie object might be from another
    173   /// DWARFUnit, but that is all encapsulated in the new DWARFDie object.
    174   ///
    175   /// Extract an attribute value from this DIE only. This call doesn't look
    176   /// for the attribute value in any DW_AT_specification or
    177   /// DW_AT_abstract_origin referenced DIEs.
    178   ///
    179   /// \param Attr the attribute to extract.
    180   /// \returns a valid DWARFDie instance if the attribute exists, or an invalid
    181   /// DWARFDie object if it doesn't.
    182   DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const;
    183   DWARFDie getAttributeValueAsReferencedDie(const DWARFFormValue &V) const;
    184 
    185   /// Extract the range base attribute from this DIE as absolute section offset.
    186   ///
    187   /// This is a utility function that checks for either the DW_AT_rnglists_base
    188   /// or DW_AT_GNU_ranges_base attribute.
    189   ///
    190   /// \returns anm optional absolute section offset value for the attribute.
    191   Optional<uint64_t> getRangesBaseAttribute() const;
    192   Optional<uint64_t> getLocBaseAttribute() const;
    193 
    194   /// Get the DW_AT_high_pc attribute value as an address.
    195   ///
    196   /// In DWARF version 4 and later the high PC can be encoded as an offset from
    197   /// the DW_AT_low_pc. This function takes care of extracting the value as an
    198   /// address or offset and adds it to the low PC if needed and returns the
    199   /// value as an optional in case the DIE doesn't have a DW_AT_high_pc
    200   /// attribute.
    201   ///
    202   /// \param LowPC the low PC that might be needed to calculate the high PC.
    203   /// \returns an optional address value for the attribute.
    204   Optional<uint64_t> getHighPC(uint64_t LowPC) const;
    205 
    206   /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
    207   /// Returns true if both attributes are present.
    208   bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,
    209                        uint64_t &SectionIndex) const;
    210 
    211   /// Get the address ranges for this DIE.
    212   ///
    213   /// Get the hi/low PC range if both attributes are available or exrtracts the
    214   /// non-contiguous address ranges from the DW_AT_ranges attribute.
    215   ///
    216   /// Extracts the range information from this DIE only. This call doesn't look
    217   /// for the range in any DW_AT_specification or DW_AT_abstract_origin DIEs.
    218   ///
    219   /// \returns a address range vector that might be empty if no address range
    220   /// information is available.
    221   Expected<DWARFAddressRangesVector> getAddressRanges() const;
    222 
    223   /// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any
    224   /// of its children.
    225   ///
    226   /// Get the hi/low PC range if both attributes are available or exrtracts the
    227   /// non-contiguous address ranges from the DW_AT_ranges attribute for this DIE
    228   /// and all children.
    229   ///
    230   /// \param Ranges the addres range vector to fill in.
    231   void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const;
    232 
    233   bool addressRangeContainsAddress(const uint64_t Address) const;
    234 
    235   Expected<DWARFLocationExpressionsVector>
    236   getLocations(dwarf::Attribute Attr) const;
    237 
    238   /// If a DIE represents a subprogram (or inlined subroutine), returns its
    239   /// mangled name (or short name, if mangled is missing). This name may be
    240   /// fetched from specification or abstract origin for this subprogram.
    241   /// Returns null if no name is found.
    242   const char *getSubroutineName(DINameKind Kind) const;
    243 
    244   /// Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin
    245   /// references if necessary. For the LinkageName case it additionaly searches
    246   /// for ShortName if LinkageName is not found.
    247   /// Returns null if no name is found.
    248   const char *getName(DINameKind Kind) const;
    249 
    250   /// Return the DIE short name resolving DW_AT_specification or
    251   /// DW_AT_abstract_origin references if necessary. Returns null if no name
    252   /// is found.
    253   const char *getShortName() const;
    254 
    255   /// Return the DIE linkage name resolving DW_AT_specification or
    256   /// DW_AT_abstract_origin references if necessary. Returns null if no name
    257   /// is found.
    258   const char *getLinkageName() const;
    259 
    260   /// Returns the declaration line (start line) for a DIE, assuming it specifies
    261   /// a subprogram. This may be fetched from specification or abstract origin
    262   /// for this subprogram by resolving DW_AT_sepcification or
    263   /// DW_AT_abstract_origin references if necessary.
    264   uint64_t getDeclLine() const;
    265   std::string getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const;
    266 
    267   /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column
    268   /// from DIE (or zeroes if they are missing). This function looks for
    269   /// DW_AT_call attributes in this DIE only, it will not resolve the attribute
    270   /// values in any DW_AT_specification or DW_AT_abstract_origin DIEs.
    271   /// \param CallFile filled in with non-zero if successful, zero if there is no
    272   /// DW_AT_call_file attribute in this DIE.
    273   /// \param CallLine filled in with non-zero if successful, zero if there is no
    274   /// DW_AT_call_line attribute in this DIE.
    275   /// \param CallColumn filled in with non-zero if successful, zero if there is
    276   /// no DW_AT_call_column attribute in this DIE.
    277   /// \param CallDiscriminator filled in with non-zero if successful, zero if
    278   /// there is no DW_AT_GNU_discriminator attribute in this DIE.
    279   void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
    280                       uint32_t &CallColumn, uint32_t &CallDiscriminator) const;
    281 
    282   class attribute_iterator;
    283 
    284   /// Get an iterator range to all attributes in the current DIE only.
    285   ///
    286   /// \returns an iterator range for the attributes of the current DIE.
    287   iterator_range<attribute_iterator> attributes() const;
    288 
    289   class iterator;
    290 
    291   iterator begin() const;
    292   iterator end() const;
    293 
    294   std::reverse_iterator<iterator> rbegin() const;
    295   std::reverse_iterator<iterator> rend() const;
    296 
    297   iterator_range<iterator> children() const;
    298 };
    299 
    300 class DWARFDie::attribute_iterator
    301     : public iterator_facade_base<attribute_iterator, std::forward_iterator_tag,
    302                                   const DWARFAttribute> {
    303   /// The DWARF DIE we are extracting attributes from.
    304   DWARFDie Die;
    305   /// The value vended to clients via the operator*() or operator->().
    306   DWARFAttribute AttrValue;
    307   /// The attribute index within the abbreviation declaration in Die.
    308   uint32_t Index;
    309 
    310   friend bool operator==(const attribute_iterator &LHS,
    311                          const attribute_iterator &RHS);
    312 
    313   /// Update the attribute index and attempt to read the attribute value. If the
    314   /// attribute is able to be read, update AttrValue and the Index member
    315   /// variable. If the attribute value is not able to be read, an appropriate
    316   /// error will be set if the Err member variable is non-NULL and the iterator
    317   /// will be set to the end value so iteration stops.
    318   void updateForIndex(const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I);
    319 
    320 public:
    321   attribute_iterator() = delete;
    322   explicit attribute_iterator(DWARFDie D, bool End);
    323 
    324   attribute_iterator &operator++();
    325   attribute_iterator &operator--();
    326   explicit operator bool() const { return AttrValue.isValid(); }
    327   const DWARFAttribute &operator*() const { return AttrValue; }
    328 };
    329 
    330 inline bool operator==(const DWARFDie::attribute_iterator &LHS,
    331                        const DWARFDie::attribute_iterator &RHS) {
    332   return LHS.Index == RHS.Index;
    333 }
    334 
    335 inline bool operator!=(const DWARFDie::attribute_iterator &LHS,
    336                        const DWARFDie::attribute_iterator &RHS) {
    337   return !(LHS == RHS);
    338 }
    339 
    340 inline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) {
    341   return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() &&
    342          LHS.getDwarfUnit() == RHS.getDwarfUnit();
    343 }
    344 
    345 inline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) {
    346   return !(LHS == RHS);
    347 }
    348 
    349 inline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) {
    350   return LHS.getOffset() < RHS.getOffset();
    351 }
    352 
    353 class DWARFDie::iterator
    354     : public iterator_facade_base<iterator, std::bidirectional_iterator_tag,
    355                                   const DWARFDie> {
    356   DWARFDie Die;
    357 
    358   friend std::reverse_iterator<llvm::DWARFDie::iterator>;
    359   friend bool operator==(const DWARFDie::iterator &LHS,
    360                          const DWARFDie::iterator &RHS);
    361 
    362 public:
    363   iterator() = default;
    364 
    365   explicit iterator(DWARFDie D) : Die(D) {}
    366 
    367   iterator &operator++() {
    368     Die = Die.getSibling();
    369     return *this;
    370   }
    371 
    372   iterator &operator--() {
    373     Die = Die.getPreviousSibling();
    374     return *this;
    375   }
    376 
    377   const DWARFDie &operator*() const { return Die; }
    378 };
    379 
    380 inline bool operator==(const DWARFDie::iterator &LHS,
    381                        const DWARFDie::iterator &RHS) {
    382   return LHS.Die == RHS.Die;
    383 }
    384 
    385 // These inline functions must follow the DWARFDie::iterator definition above
    386 // as they use functions from that class.
    387 inline DWARFDie::iterator DWARFDie::begin() const {
    388   return iterator(getFirstChild());
    389 }
    390 
    391 inline DWARFDie::iterator DWARFDie::end() const {
    392   return iterator(getLastChild());
    393 }
    394 
    395 inline iterator_range<DWARFDie::iterator> DWARFDie::children() const {
    396   return make_range(begin(), end());
    397 }
    398 
    399 } // end namespace llvm
    400 
    401 namespace std {
    402 
    403 template <>
    404 class reverse_iterator<llvm::DWARFDie::iterator>
    405     : public llvm::iterator_facade_base<
    406           reverse_iterator<llvm::DWARFDie::iterator>,
    407           bidirectional_iterator_tag, const llvm::DWARFDie> {
    408 
    409 private:
    410   llvm::DWARFDie Die;
    411   bool AtEnd;
    412 
    413 public:
    414   reverse_iterator(llvm::DWARFDie::iterator It)
    415       : Die(It.Die), AtEnd(!It.Die.getPreviousSibling()) {
    416     if (!AtEnd)
    417       Die = Die.getPreviousSibling();
    418   }
    419 
    420   llvm::DWARFDie::iterator base() const {
    421     return llvm::DWARFDie::iterator(AtEnd ? Die : Die.getSibling());
    422   }
    423 
    424   reverse_iterator<llvm::DWARFDie::iterator> &operator++() {
    425     assert(!AtEnd && "Incrementing rend");
    426     llvm::DWARFDie D = Die.getPreviousSibling();
    427     if (D)
    428       Die = D;
    429     else
    430       AtEnd = true;
    431     return *this;
    432   }
    433 
    434   reverse_iterator<llvm::DWARFDie::iterator> &operator--() {
    435     if (AtEnd) {
    436       AtEnd = false;
    437       return *this;
    438     }
    439     Die = Die.getSibling();
    440     assert(!Die.isNULL() && "Decrementing rbegin");
    441     return *this;
    442   }
    443 
    444   const llvm::DWARFDie &operator*() const {
    445     assert(Die.isValid());
    446     return Die;
    447   }
    448 
    449   // FIXME: We should be able to specify the equals operator as a friend, but
    450   //        that causes the compiler to think the operator overload is ambiguous
    451   //        with the friend declaration and the actual definition as candidates.
    452   bool equals(const reverse_iterator<llvm::DWARFDie::iterator> &RHS) const {
    453     return Die == RHS.Die && AtEnd == RHS.AtEnd;
    454   }
    455 };
    456 
    457 } // namespace std
    458 
    459 namespace llvm {
    460 
    461 inline bool operator==(const std::reverse_iterator<DWARFDie::iterator> &LHS,
    462                        const std::reverse_iterator<DWARFDie::iterator> &RHS) {
    463   return LHS.equals(RHS);
    464 }
    465 
    466 inline bool operator!=(const std::reverse_iterator<DWARFDie::iterator> &LHS,
    467                        const std::reverse_iterator<DWARFDie::iterator> &RHS) {
    468   return !(LHS == RHS);
    469 }
    470 
    471 inline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rbegin() const {
    472   return llvm::make_reverse_iterator(end());
    473 }
    474 
    475 inline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rend() const {
    476   return llvm::make_reverse_iterator(begin());
    477 }
    478 
    479 } // end namespace llvm
    480 
    481 #endif // LLVM_DEBUGINFO_DWARF_DWARFDIE_H
    482