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