DWARFDie.h revision 353358
1321369Sdim//===- DWARFDie.h -----------------------------------------------*- C++ -*-===// 2311116Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6311116Sdim// 7311116Sdim//===----------------------------------------------------------------------===// 8311116Sdim 9321369Sdim#ifndef LLVM_DEBUGINFO_DWARFDIE_H 10321369Sdim#define LLVM_DEBUGINFO_DWARFDIE_H 11311116Sdim 12321369Sdim#include "llvm/ADT/ArrayRef.h" 13321369Sdim#include "llvm/ADT/Optional.h" 14311544Sdim#include "llvm/ADT/iterator.h" 15311544Sdim#include "llvm/ADT/iterator_range.h" 16321369Sdim#include "llvm/BinaryFormat/Dwarf.h" 17321369Sdim#include "llvm/DebugInfo/DIContext.h" 18341825Sdim#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" 19321369Sdim#include "llvm/DebugInfo/DWARF/DWARFAttribute.h" 20311116Sdim#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" 21321369Sdim#include <cassert> 22321369Sdim#include <cstdint> 23321369Sdim#include <iterator> 24311116Sdim 25311116Sdimnamespace llvm { 26321369Sdim 27311116Sdimclass DWARFUnit; 28311116Sdimclass raw_ostream; 29321369Sdim 30311116Sdim//===----------------------------------------------------------------------===// 31311116Sdim/// Utility class that carries the DWARF compile/type unit and the debug info 32311116Sdim/// entry in an object. 33311116Sdim/// 34311116Sdim/// When accessing information from a debug info entry we always need to DWARF 35311116Sdim/// compile/type unit in order to extract the info correctly as some information 36311116Sdim/// is relative to the compile/type unit. Prior to this class the DWARFUnit and 37311116Sdim/// the DWARFDebugInfoEntry was passed around separately and there was the 38311116Sdim/// possibility for error if the wrong DWARFUnit was used to extract a unit 39311116Sdim/// relative offset. This class helps to ensure that this doesn't happen and 40311116Sdim/// also simplifies the attribute extraction calls by not having to specify the 41311116Sdim/// DWARFUnit for each call. 42311116Sdimclass DWARFDie { 43321369Sdim DWARFUnit *U = nullptr; 44321369Sdim const DWARFDebugInfoEntry *Die = nullptr; 45321369Sdim 46311116Sdimpublic: 47321369Sdim DWARFDie() = default; 48341825Sdim DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry *D) : U(Unit), Die(D) {} 49321369Sdim 50311116Sdim bool isValid() const { return U && Die; } 51311116Sdim explicit operator bool() const { return isValid(); } 52311116Sdim const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; } 53311116Sdim DWARFUnit *getDwarfUnit() const { return U; } 54311116Sdim 55311116Sdim /// Get the abbreviation declaration for this DIE. 56311116Sdim /// 57311116Sdim /// \returns the abbreviation declaration or NULL for null tags. 58311116Sdim const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { 59311116Sdim assert(isValid() && "must check validity prior to calling"); 60311116Sdim return Die->getAbbreviationDeclarationPtr(); 61311116Sdim } 62311116Sdim 63311116Sdim /// Get the absolute offset into the debug info or types section. 64311116Sdim /// 65311116Sdim /// \returns the DIE offset or -1U if invalid. 66311116Sdim uint32_t getOffset() const { 67311116Sdim assert(isValid() && "must check validity prior to calling"); 68311116Sdim return Die->getOffset(); 69311116Sdim } 70321369Sdim 71311116Sdim dwarf::Tag getTag() const { 72311116Sdim auto AbbrevDecl = getAbbreviationDeclarationPtr(); 73311116Sdim if (AbbrevDecl) 74311116Sdim return AbbrevDecl->getTag(); 75311116Sdim return dwarf::DW_TAG_null; 76311116Sdim } 77311116Sdim 78311116Sdim bool hasChildren() const { 79311116Sdim assert(isValid() && "must check validity prior to calling"); 80311116Sdim return Die->hasChildren(); 81311116Sdim } 82321369Sdim 83311116Sdim /// Returns true for a valid DIE that terminates a sibling chain. 84341825Sdim bool isNULL() const { return getAbbreviationDeclarationPtr() == nullptr; } 85321369Sdim 86311116Sdim /// Returns true if DIE represents a subprogram (not inlined). 87311116Sdim bool isSubprogramDIE() const; 88311116Sdim 89311116Sdim /// Returns true if DIE represents a subprogram or an inlined subroutine. 90311116Sdim bool isSubroutineDIE() const; 91311116Sdim 92311116Sdim /// Get the parent of this DIE object. 93311116Sdim /// 94311116Sdim /// \returns a valid DWARFDie instance if this object has a parent or an 95311116Sdim /// invalid DWARFDie instance if it doesn't. 96311116Sdim DWARFDie getParent() const; 97321369Sdim 98311116Sdim /// Get the sibling of this DIE object. 99311116Sdim /// 100311116Sdim /// \returns a valid DWARFDie instance if this object has a sibling or an 101311116Sdim /// invalid DWARFDie instance if it doesn't. 102311116Sdim DWARFDie getSibling() const; 103321369Sdim 104341825Sdim /// Get the previous sibling of this DIE object. 105341825Sdim /// 106341825Sdim /// \returns a valid DWARFDie instance if this object has a sibling or an 107341825Sdim /// invalid DWARFDie instance if it doesn't. 108341825Sdim DWARFDie getPreviousSibling() const; 109341825Sdim 110311116Sdim /// Get the first child of this DIE object. 111311116Sdim /// 112311116Sdim /// \returns a valid DWARFDie instance if this object has children or an 113311116Sdim /// invalid DWARFDie instance if it doesn't. 114327952Sdim DWARFDie getFirstChild() const; 115321369Sdim 116341825Sdim /// Get the last child of this DIE object. 117341825Sdim /// 118341825Sdim /// \returns a valid null DWARFDie instance if this object has children or an 119341825Sdim /// invalid DWARFDie instance if it doesn't. 120341825Sdim DWARFDie getLastChild() const; 121341825Sdim 122311116Sdim /// Dump the DIE and all of its attributes to the supplied stream. 123311116Sdim /// 124311116Sdim /// \param OS the stream to use for output. 125311116Sdim /// \param indent the number of characters to indent each line that is output. 126327952Sdim void dump(raw_ostream &OS, unsigned indent = 0, 127321369Sdim DIDumpOptions DumpOpts = DIDumpOptions()) const; 128321369Sdim 129327952Sdim /// Convenience zero-argument overload for debugging. 130327952Sdim LLVM_DUMP_METHOD void dump() const; 131327952Sdim 132311116Sdim /// Extract the specified attribute from this DIE. 133311116Sdim /// 134311116Sdim /// Extract an attribute value from this DIE only. This call doesn't look 135311116Sdim /// for the attribute value in any DW_AT_specification or 136311116Sdim /// DW_AT_abstract_origin referenced DIEs. 137311116Sdim /// 138311116Sdim /// \param Attr the attribute to extract. 139311116Sdim /// \returns an optional DWARFFormValue that will have the form value if the 140311116Sdim /// attribute was successfully extracted. 141321369Sdim Optional<DWARFFormValue> find(dwarf::Attribute Attr) const; 142321369Sdim 143321369Sdim /// Extract the first value of any attribute in Attrs from this DIE. 144311116Sdim /// 145321369Sdim /// Extract the first attribute that matches from this DIE only. This call 146321369Sdim /// doesn't look for the attribute value in any DW_AT_specification or 147321369Sdim /// DW_AT_abstract_origin referenced DIEs. The attributes will be searched 148321369Sdim /// linearly in the order they are specified within Attrs. 149311116Sdim /// 150321369Sdim /// \param Attrs an array of DWARF attribute to look for. 151321369Sdim /// \returns an optional that has a valid DWARFFormValue for the first 152321369Sdim /// matching attribute in Attrs, or None if none of the attributes in Attrs 153321369Sdim /// exist in this DIE. 154321369Sdim Optional<DWARFFormValue> find(ArrayRef<dwarf::Attribute> Attrs) const; 155321369Sdim 156321369Sdim /// Extract the first value of any attribute in Attrs from this DIE and 157321369Sdim /// recurse into any DW_AT_specification or DW_AT_abstract_origin referenced 158321369Sdim /// DIEs. 159311116Sdim /// 160321369Sdim /// \param Attrs an array of DWARF attribute to look for. 161321369Sdim /// \returns an optional that has a valid DWARFFormValue for the first 162321369Sdim /// matching attribute in Attrs, or None if none of the attributes in Attrs 163321369Sdim /// exist in this DIE or in any DW_AT_specification or DW_AT_abstract_origin 164321369Sdim /// DIEs. 165321369Sdim Optional<DWARFFormValue> 166321369Sdim findRecursively(ArrayRef<dwarf::Attribute> Attrs) const; 167311116Sdim 168311116Sdim /// Extract the specified attribute from this DIE as the referenced DIE. 169311116Sdim /// 170311116Sdim /// Regardless of the reference type, return the correct DWARFDie instance if 171311116Sdim /// the attribute exists. The returned DWARFDie object might be from another 172311116Sdim /// DWARFUnit, but that is all encapsulated in the new DWARFDie object. 173311116Sdim /// 174311116Sdim /// Extract an attribute value from this DIE only. This call doesn't look 175311116Sdim /// for the attribute value in any DW_AT_specification or 176311116Sdim /// DW_AT_abstract_origin referenced DIEs. 177311116Sdim /// 178311116Sdim /// \param Attr the attribute to extract. 179311116Sdim /// \returns a valid DWARFDie instance if the attribute exists, or an invalid 180311116Sdim /// DWARFDie object if it doesn't. 181311116Sdim DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const; 182344779Sdim DWARFDie getAttributeValueAsReferencedDie(const DWARFFormValue &V) const; 183311116Sdim 184311116Sdim /// Extract the range base attribute from this DIE as absolute section offset. 185311116Sdim /// 186311116Sdim /// This is a utility function that checks for either the DW_AT_rnglists_base 187311116Sdim /// or DW_AT_GNU_ranges_base attribute. 188311116Sdim /// 189311116Sdim /// \returns anm optional absolute section offset value for the attribute. 190311116Sdim Optional<uint64_t> getRangesBaseAttribute() const; 191321369Sdim 192311116Sdim /// Get the DW_AT_high_pc attribute value as an address. 193311116Sdim /// 194311116Sdim /// In DWARF version 4 and later the high PC can be encoded as an offset from 195311116Sdim /// the DW_AT_low_pc. This function takes care of extracting the value as an 196311116Sdim /// address or offset and adds it to the low PC if needed and returns the 197311116Sdim /// value as an optional in case the DIE doesn't have a DW_AT_high_pc 198311116Sdim /// attribute. 199311116Sdim /// 200311116Sdim /// \param LowPC the low PC that might be needed to calculate the high PC. 201311116Sdim /// \returns an optional address value for the attribute. 202311116Sdim Optional<uint64_t> getHighPC(uint64_t LowPC) const; 203311116Sdim 204311116Sdim /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. 205311116Sdim /// Returns true if both attributes are present. 206321369Sdim bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, 207321369Sdim uint64_t &SectionIndex) const; 208321369Sdim 209311116Sdim /// Get the address ranges for this DIE. 210311116Sdim /// 211311116Sdim /// Get the hi/low PC range if both attributes are available or exrtracts the 212311116Sdim /// non-contiguous address ranges from the DW_AT_ranges attribute. 213311116Sdim /// 214311116Sdim /// Extracts the range information from this DIE only. This call doesn't look 215311116Sdim /// for the range in any DW_AT_specification or DW_AT_abstract_origin DIEs. 216311116Sdim /// 217311116Sdim /// \returns a address range vector that might be empty if no address range 218311116Sdim /// information is available. 219341825Sdim Expected<DWARFAddressRangesVector> getAddressRanges() const; 220321369Sdim 221311116Sdim /// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any 222311116Sdim /// of its children. 223311116Sdim /// 224311116Sdim /// Get the hi/low PC range if both attributes are available or exrtracts the 225311116Sdim /// non-contiguous address ranges from the DW_AT_ranges attribute for this DIE 226311116Sdim /// and all children. 227311116Sdim /// 228311116Sdim /// \param Ranges the addres range vector to fill in. 229311116Sdim void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const; 230321369Sdim 231311116Sdim bool addressRangeContainsAddress(const uint64_t Address) const; 232321369Sdim 233311116Sdim /// If a DIE represents a subprogram (or inlined subroutine), returns its 234311116Sdim /// mangled name (or short name, if mangled is missing). This name may be 235311116Sdim /// fetched from specification or abstract origin for this subprogram. 236311116Sdim /// Returns null if no name is found. 237311116Sdim const char *getSubroutineName(DINameKind Kind) const; 238321369Sdim 239311116Sdim /// Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin 240311116Sdim /// references if necessary. Returns null if no name is found. 241311116Sdim const char *getName(DINameKind Kind) const; 242321369Sdim 243321369Sdim /// Returns the declaration line (start line) for a DIE, assuming it specifies 244321369Sdim /// a subprogram. This may be fetched from specification or abstract origin 245321369Sdim /// for this subprogram by resolving DW_AT_sepcification or 246321369Sdim /// DW_AT_abstract_origin references if necessary. 247321369Sdim uint64_t getDeclLine() const; 248321369Sdim 249311116Sdim /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column 250311116Sdim /// from DIE (or zeroes if they are missing). This function looks for 251311116Sdim /// DW_AT_call attributes in this DIE only, it will not resolve the attribute 252311116Sdim /// values in any DW_AT_specification or DW_AT_abstract_origin DIEs. 253311116Sdim /// \param CallFile filled in with non-zero if successful, zero if there is no 254311116Sdim /// DW_AT_call_file attribute in this DIE. 255311116Sdim /// \param CallLine filled in with non-zero if successful, zero if there is no 256311116Sdim /// DW_AT_call_line attribute in this DIE. 257311116Sdim /// \param CallColumn filled in with non-zero if successful, zero if there is 258311116Sdim /// no DW_AT_call_column attribute in this DIE. 259321369Sdim /// \param CallDiscriminator filled in with non-zero if successful, zero if 260321369Sdim /// there is no DW_AT_GNU_discriminator attribute in this DIE. 261311116Sdim void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, 262321369Sdim uint32_t &CallColumn, uint32_t &CallDiscriminator) const; 263311116Sdim 264321369Sdim class attribute_iterator; 265321369Sdim 266321369Sdim /// Get an iterator range to all attributes in the current DIE only. 267321369Sdim /// 268321369Sdim /// \returns an iterator range for the attributes of the current DIE. 269321369Sdim iterator_range<attribute_iterator> attributes() const; 270321369Sdim 271311544Sdim class iterator; 272321369Sdim 273311544Sdim iterator begin() const; 274311544Sdim iterator end() const; 275341825Sdim 276341825Sdim std::reverse_iterator<iterator> rbegin() const; 277341825Sdim std::reverse_iterator<iterator> rend() const; 278341825Sdim 279311544Sdim iterator_range<iterator> children() const; 280311116Sdim}; 281311116Sdim 282341825Sdimclass DWARFDie::attribute_iterator 283341825Sdim : public iterator_facade_base<attribute_iterator, std::forward_iterator_tag, 284341825Sdim const DWARFAttribute> { 285321369Sdim /// The DWARF DIE we are extracting attributes from. 286321369Sdim DWARFDie Die; 287321369Sdim /// The value vended to clients via the operator*() or operator->(). 288321369Sdim DWARFAttribute AttrValue; 289321369Sdim /// The attribute index within the abbreviation declaration in Die. 290321369Sdim uint32_t Index; 291321369Sdim 292341825Sdim friend bool operator==(const attribute_iterator &LHS, 293341825Sdim const attribute_iterator &RHS); 294341825Sdim 295321369Sdim /// Update the attribute index and attempt to read the attribute value. If the 296321369Sdim /// attribute is able to be read, update AttrValue and the Index member 297321369Sdim /// variable. If the attribute value is not able to be read, an appropriate 298321369Sdim /// error will be set if the Err member variable is non-NULL and the iterator 299321369Sdim /// will be set to the end value so iteration stops. 300321369Sdim void updateForIndex(const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I); 301321369Sdim 302321369Sdimpublic: 303321369Sdim attribute_iterator() = delete; 304321369Sdim explicit attribute_iterator(DWARFDie D, bool End); 305321369Sdim 306321369Sdim attribute_iterator &operator++(); 307341825Sdim attribute_iterator &operator--(); 308321369Sdim explicit operator bool() const { return AttrValue.isValid(); } 309321369Sdim const DWARFAttribute &operator*() const { return AttrValue; } 310321369Sdim}; 311321369Sdim 312341825Sdiminline bool operator==(const DWARFDie::attribute_iterator &LHS, 313341825Sdim const DWARFDie::attribute_iterator &RHS) { 314341825Sdim return LHS.Index == RHS.Index; 315341825Sdim} 316341825Sdim 317341825Sdiminline bool operator!=(const DWARFDie::attribute_iterator &LHS, 318341825Sdim const DWARFDie::attribute_iterator &RHS) { 319341825Sdim return !(LHS == RHS); 320341825Sdim} 321341825Sdim 322311544Sdiminline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) { 323311544Sdim return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() && 324341825Sdim LHS.getDwarfUnit() == RHS.getDwarfUnit(); 325311544Sdim} 326311116Sdim 327311544Sdiminline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) { 328311544Sdim return !(LHS == RHS); 329311544Sdim} 330311544Sdim 331327952Sdiminline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) { 332327952Sdim return LHS.getOffset() < RHS.getOffset(); 333327952Sdim} 334327952Sdim 335341825Sdimclass DWARFDie::iterator 336341825Sdim : public iterator_facade_base<iterator, std::bidirectional_iterator_tag, 337341825Sdim const DWARFDie> { 338311544Sdim DWARFDie Die; 339341825Sdim 340341825Sdim friend std::reverse_iterator<llvm::DWARFDie::iterator>; 341341825Sdim friend bool operator==(const DWARFDie::iterator &LHS, 342341825Sdim const DWARFDie::iterator &RHS); 343341825Sdim 344311544Sdimpublic: 345311544Sdim iterator() = default; 346321369Sdim 347341825Sdim explicit iterator(DWARFDie D) : Die(D) {} 348321369Sdim 349311544Sdim iterator &operator++() { 350311544Sdim Die = Die.getSibling(); 351311544Sdim return *this; 352311544Sdim } 353321369Sdim 354341825Sdim iterator &operator--() { 355341825Sdim Die = Die.getPreviousSibling(); 356341825Sdim return *this; 357341825Sdim } 358341825Sdim 359311544Sdim const DWARFDie &operator*() const { return Die; } 360311544Sdim}; 361311544Sdim 362341825Sdiminline bool operator==(const DWARFDie::iterator &LHS, 363341825Sdim const DWARFDie::iterator &RHS) { 364341825Sdim return LHS.Die == RHS.Die; 365341825Sdim} 366341825Sdim 367341825Sdiminline bool operator!=(const DWARFDie::iterator &LHS, 368341825Sdim const DWARFDie::iterator &RHS) { 369341825Sdim return !(LHS == RHS); 370341825Sdim} 371341825Sdim 372311544Sdim// These inline functions must follow the DWARFDie::iterator definition above 373311544Sdim// as they use functions from that class. 374311544Sdiminline DWARFDie::iterator DWARFDie::begin() const { 375311544Sdim return iterator(getFirstChild()); 376311544Sdim} 377311544Sdim 378311544Sdiminline DWARFDie::iterator DWARFDie::end() const { 379341825Sdim return iterator(getLastChild()); 380311544Sdim} 381311544Sdim 382311544Sdiminline iterator_range<DWARFDie::iterator> DWARFDie::children() const { 383311544Sdim return make_range(begin(), end()); 384311544Sdim} 385311544Sdim 386311116Sdim} // end namespace llvm 387311116Sdim 388341825Sdimnamespace std { 389341825Sdim 390341825Sdimtemplate <> 391341825Sdimclass reverse_iterator<llvm::DWARFDie::iterator> 392341825Sdim : public llvm::iterator_facade_base< 393341825Sdim reverse_iterator<llvm::DWARFDie::iterator>, 394341825Sdim bidirectional_iterator_tag, const llvm::DWARFDie> { 395341825Sdim 396341825Sdimprivate: 397341825Sdim llvm::DWARFDie Die; 398341825Sdim bool AtEnd; 399341825Sdim 400341825Sdimpublic: 401341825Sdim reverse_iterator(llvm::DWARFDie::iterator It) 402341825Sdim : Die(It.Die), AtEnd(!It.Die.getPreviousSibling()) { 403341825Sdim if (!AtEnd) 404341825Sdim Die = Die.getPreviousSibling(); 405341825Sdim } 406341825Sdim 407344779Sdim llvm::DWARFDie::iterator base() const { 408344779Sdim return llvm::DWARFDie::iterator(AtEnd ? Die : Die.getSibling()); 409344779Sdim } 410344779Sdim 411341825Sdim reverse_iterator<llvm::DWARFDie::iterator> &operator++() { 412341825Sdim assert(!AtEnd && "Incrementing rend"); 413341825Sdim llvm::DWARFDie D = Die.getPreviousSibling(); 414341825Sdim if (D) 415341825Sdim Die = D; 416341825Sdim else 417341825Sdim AtEnd = true; 418341825Sdim return *this; 419341825Sdim } 420341825Sdim 421341825Sdim reverse_iterator<llvm::DWARFDie::iterator> &operator--() { 422341825Sdim if (AtEnd) { 423341825Sdim AtEnd = false; 424341825Sdim return *this; 425341825Sdim } 426341825Sdim Die = Die.getSibling(); 427341825Sdim assert(!Die.isNULL() && "Decrementing rbegin"); 428341825Sdim return *this; 429341825Sdim } 430341825Sdim 431341825Sdim const llvm::DWARFDie &operator*() const { 432341825Sdim assert(Die.isValid()); 433341825Sdim return Die; 434341825Sdim } 435341825Sdim 436341825Sdim // FIXME: We should be able to specify the equals operator as a friend, but 437341825Sdim // that causes the compiler to think the operator overload is ambiguous 438341825Sdim // with the friend declaration and the actual definition as candidates. 439341825Sdim bool equals(const reverse_iterator<llvm::DWARFDie::iterator> &RHS) const { 440341825Sdim return Die == RHS.Die && AtEnd == RHS.AtEnd; 441341825Sdim } 442341825Sdim}; 443341825Sdim 444341825Sdim} // namespace std 445341825Sdim 446341825Sdimnamespace llvm { 447341825Sdim 448341825Sdiminline bool operator==(const std::reverse_iterator<DWARFDie::iterator> &LHS, 449341825Sdim const std::reverse_iterator<DWARFDie::iterator> &RHS) { 450341825Sdim return LHS.equals(RHS); 451341825Sdim} 452341825Sdim 453341825Sdiminline bool operator!=(const std::reverse_iterator<DWARFDie::iterator> &LHS, 454341825Sdim const std::reverse_iterator<DWARFDie::iterator> &RHS) { 455341825Sdim return !(LHS == RHS); 456341825Sdim} 457341825Sdim 458341825Sdiminline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rbegin() const { 459341825Sdim return llvm::make_reverse_iterator(end()); 460341825Sdim} 461341825Sdim 462341825Sdiminline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rend() const { 463341825Sdim return llvm::make_reverse_iterator(begin()); 464341825Sdim} 465341825Sdim 466341825Sdim} // end namespace llvm 467341825Sdim 468321369Sdim#endif // LLVM_DEBUGINFO_DWARFDIE_H 469