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