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