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_LIB_DEBUGINFO_DWARFUNIT_H
11 #define LLVM_LIB_DEBUGINFO_DWARFUNIT_H
12 
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
15 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
16 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
17 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
18 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
19 #include <vector>
20 
21 namespace llvm {
22 
23 namespace object {
24 class ObjectFile;
25 }
26 
27 class DWARFContext;
28 class DWARFDebugAbbrev;
29 class DWARFUnit;
30 class StringRef;
31 class raw_ostream;
32 
33 /// Base class for all DWARFUnitSection classes. This provides the
34 /// functionality common to all unit types.
35 class DWARFUnitSectionBase {
36 public:
37   /// Returns the Unit that contains the given section offset in the
38   /// same section this Unit originated from.
39   virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0;
40 
41   void parse(DWARFContext &C, const DWARFSection &Section);
42   void parseDWO(DWARFContext &C, const DWARFSection &DWOSection);
43 
44 protected:
45   virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
46                          const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
47                          StringRef SOS, StringRef AOS, bool isLittleEndian) = 0;
48 
49   ~DWARFUnitSectionBase() = default;
50 };
51 
52 /// Concrete instance of DWARFUnitSection, specialized for one Unit type.
53 template<typename UnitType>
54 class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
55                                public DWARFUnitSectionBase {
56 
57   struct UnitOffsetComparator {
operatorUnitOffsetComparator58     bool operator()(uint32_t LHS,
59                     const std::unique_ptr<UnitType> &RHS) const {
60       return LHS < RHS->getNextUnitOffset();
61     }
62   };
63 
64   bool Parsed;
65 
66 public:
DWARFUnitSection()67   DWARFUnitSection() : Parsed(false) {}
DWARFUnitSection(DWARFUnitSection && DUS)68   DWARFUnitSection(DWARFUnitSection &&DUS) :
69     SmallVector<std::unique_ptr<UnitType>, 1>(std::move(DUS)), Parsed(DUS.Parsed) {}
70 
71   typedef llvm::SmallVectorImpl<std::unique_ptr<UnitType>> UnitVector;
72   typedef typename UnitVector::iterator iterator;
73   typedef llvm::iterator_range<typename UnitVector::iterator> iterator_range;
74 
getUnitForOffset(uint32_t Offset)75   UnitType *getUnitForOffset(uint32_t Offset) const override {
76     auto *CU = std::upper_bound(this->begin(), this->end(), Offset,
77                                 UnitOffsetComparator());
78     if (CU != this->end())
79       return CU->get();
80     return nullptr;
81   }
82 
83 private:
parseImpl(DWARFContext & Context,const DWARFSection & Section,const DWARFDebugAbbrev * DA,StringRef RS,StringRef SS,StringRef SOS,StringRef AOS,bool LE)84   void parseImpl(DWARFContext &Context, const DWARFSection &Section,
85                  const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
86                  StringRef SOS, StringRef AOS, bool LE) override {
87     if (Parsed)
88       return;
89     DataExtractor Data(Section.Data, LE, 0);
90     uint32_t Offset = 0;
91     while (Data.isValidOffset(Offset)) {
92       auto U = llvm::make_unique<UnitType>(Context, Section, DA, RS, SS, SOS,
93                                            AOS, LE, *this);
94       if (!U->extract(Data, &Offset))
95         break;
96       this->push_back(std::move(U));
97       Offset = this->back()->getNextUnitOffset();
98     }
99     Parsed = true;
100   }
101 };
102 
103 class DWARFUnit {
104   DWARFContext &Context;
105   // Section containing this DWARFUnit.
106   const DWARFSection &InfoSection;
107 
108   const DWARFDebugAbbrev *Abbrev;
109   StringRef RangeSection;
110   uint32_t RangeSectionBase;
111   StringRef StringSection;
112   StringRef StringOffsetSection;
113   StringRef AddrOffsetSection;
114   uint32_t AddrOffsetSectionBase;
115   bool isLittleEndian;
116   const DWARFUnitSectionBase &UnitSection;
117 
118   uint32_t Offset;
119   uint32_t Length;
120   uint16_t Version;
121   const DWARFAbbreviationDeclarationSet *Abbrevs;
122   uint8_t AddrSize;
123   uint64_t BaseAddr;
124   // The compile unit debug information entry items.
125   std::vector<DWARFDebugInfoEntryMinimal> DieArray;
126 
127   class DWOHolder {
128     object::OwningBinary<object::ObjectFile> DWOFile;
129     std::unique_ptr<DWARFContext> DWOContext;
130     DWARFUnit *DWOU;
131   public:
132     DWOHolder(StringRef DWOPath);
getUnit()133     DWARFUnit *getUnit() const { return DWOU; }
134   };
135   std::unique_ptr<DWOHolder> DWO;
136 
137 protected:
138   virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
139   /// Size in bytes of the unit header.
getHeaderSize()140   virtual uint32_t getHeaderSize() const { return 11; }
141 
142 public:
143   DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
144             const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
145             StringRef SOS, StringRef AOS, bool LE,
146             const DWARFUnitSectionBase &UnitSection);
147 
148   virtual ~DWARFUnit();
149 
getContext()150   DWARFContext& getContext() const { return Context; }
151 
getStringSection()152   StringRef getStringSection() const { return StringSection; }
getStringOffsetSection()153   StringRef getStringOffsetSection() const { return StringOffsetSection; }
setAddrOffsetSection(StringRef AOS,uint32_t Base)154   void setAddrOffsetSection(StringRef AOS, uint32_t Base) {
155     AddrOffsetSection = AOS;
156     AddrOffsetSectionBase = Base;
157   }
setRangesSection(StringRef RS,uint32_t Base)158   void setRangesSection(StringRef RS, uint32_t Base) {
159     RangeSection = RS;
160     RangeSectionBase = Base;
161   }
162 
163   bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
164   // FIXME: Result should be uint64_t in DWARF64.
165   bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const;
166 
getDebugInfoExtractor()167   DataExtractor getDebugInfoExtractor() const {
168     return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize);
169   }
getStringExtractor()170   DataExtractor getStringExtractor() const {
171     return DataExtractor(StringSection, false, 0);
172   }
173 
getRelocMap()174   const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; }
175 
176   bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
177 
178   /// extractRangeList - extracts the range list referenced by this compile
179   /// unit from .debug_ranges section. Returns true on success.
180   /// Requires that compile unit is already extracted.
181   bool extractRangeList(uint32_t RangeListOffset,
182                         DWARFDebugRangeList &RangeList) const;
183   void clear();
getOffset()184   uint32_t getOffset() const { return Offset; }
getNextUnitOffset()185   uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
getLength()186   uint32_t getLength() const { return Length; }
getVersion()187   uint16_t getVersion() const { return Version; }
getAbbreviations()188   const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
189     return Abbrevs;
190   }
getAddressByteSize()191   uint8_t getAddressByteSize() const { return AddrSize; }
getBaseAddress()192   uint64_t getBaseAddress() const { return BaseAddr; }
193 
setBaseAddress(uint64_t base_addr)194   void setBaseAddress(uint64_t base_addr) {
195     BaseAddr = base_addr;
196   }
197 
198   const DWARFDebugInfoEntryMinimal *
199   getCompileUnitDIE(bool extract_cu_die_only = true) {
200     extractDIEsIfNeeded(extract_cu_die_only);
201     return DieArray.empty() ? nullptr : &DieArray[0];
202   }
203 
204   const char *getCompilationDir();
205   uint64_t getDWOId();
206 
207   void collectAddressRanges(DWARFAddressRangesVector &CURanges);
208 
209   /// getInlinedChainForAddress - fetches inlined chain for a given address.
210   /// Returns empty chain if there is no subprogram containing address. The
211   /// chain is valid as long as parsed compile unit DIEs are not cleared.
212   DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address);
213 
214   /// getUnitSection - Return the DWARFUnitSection containing this unit.
getUnitSection()215   const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; }
216 
217   /// \brief Returns the number of DIEs in the unit. Parses the unit
218   /// if necessary.
getNumDIEs()219   unsigned getNumDIEs() {
220     extractDIEsIfNeeded(false);
221     return DieArray.size();
222   }
223 
224   /// \brief Return the index of a DIE inside the unit's DIE vector.
225   ///
226   /// It is illegal to call this method with a DIE that hasn't be
227   /// created by this unit. In other word, it's illegal to call this
228   /// method on a DIE that isn't accessible by following
229   /// children/sibling links starting from this unit's
230   /// getCompileUnitDIE().
getDIEIndex(const DWARFDebugInfoEntryMinimal * DIE)231   uint32_t getDIEIndex(const DWARFDebugInfoEntryMinimal *DIE) {
232     assert(!DieArray.empty() && DIE >= &DieArray[0] &&
233            DIE < &DieArray[0] + DieArray.size());
234     return DIE - &DieArray[0];
235   }
236 
237   /// \brief Return the DIE object at the given index.
getDIEAtIndex(unsigned Index)238   const DWARFDebugInfoEntryMinimal *getDIEAtIndex(unsigned Index) const {
239     assert(Index < DieArray.size());
240     return &DieArray[Index];
241   }
242 
243   /// \brief Return the DIE object for a given offset inside the
244   /// unit's DIE vector.
245   ///
246   /// The unit needs to have his DIEs extracted for this method to work.
getDIEForOffset(uint32_t Offset)247   const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) const {
248     assert(!DieArray.empty());
249     auto it = std::lower_bound(
250         DieArray.begin(), DieArray.end(), Offset,
251         [=](const DWARFDebugInfoEntryMinimal &LHS, uint32_t Offset) {
252           return LHS.getOffset() < Offset;
253         });
254     return it == DieArray.end() ? nullptr : &*it;
255   }
256 
257 private:
258   /// Size in bytes of the .debug_info data associated with this compile unit.
getDebugInfoSize()259   size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); }
260 
261   /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
262   /// hasn't already been done. Returns the number of DIEs parsed at this call.
263   size_t extractDIEsIfNeeded(bool CUDieOnly);
264   /// extractDIEsToVector - Appends all parsed DIEs to a vector.
265   void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
266                            std::vector<DWARFDebugInfoEntryMinimal> &DIEs) const;
267   /// setDIERelations - We read in all of the DIE entries into our flat list
268   /// of DIE entries and now we need to go back through all of them and set the
269   /// parent, sibling and child pointers for quick DIE navigation.
270   void setDIERelations();
271   /// clearDIEs - Clear parsed DIEs to keep memory usage low.
272   void clearDIEs(bool KeepCUDie);
273 
274   /// parseDWO - Parses .dwo file for current compile unit. Returns true if
275   /// it was actually constructed.
276   bool parseDWO();
277 
278   /// getSubprogramForAddress - Returns subprogram DIE with address range
279   /// encompassing the provided address. The pointer is alive as long as parsed
280   /// compile unit DIEs are not cleared.
281   const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address);
282 };
283 
284 }
285 
286 #endif
287