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