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 22namespace llvm { 23 24namespace object { 25class ObjectFile; 26} 27 28class DWARFContext; 29class DWARFDebugAbbrev; 30class DWARFUnit; 31class StringRef; 32class raw_ostream; 33 34/// Base class for all DWARFUnitSection classes. This provides the 35/// functionality common to all unit types. 36class DWARFUnitSectionBase { 37public: 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 46protected: 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 55const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, 56 DWARFSectionKind Kind); 57 58/// Concrete instance of DWARFUnitSection, specialized for one Unit type. 59template<typename UnitType> 60class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>, 61 public DWARFUnitSectionBase { 62 bool Parsed = false; 63 64public: 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 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 80private: 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 103class 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); 135 DWARFUnit *getUnit() const { return DWOU; } 136 }; 137 std::unique_ptr<DWOHolder> DWO; 138 139 const DWARFUnitIndex::Entry *IndexEntry; 140 141protected: 142 virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); 143 /// Size in bytes of the unit header. 144 virtual uint32_t getHeaderSize() const { return 11; } 145 146public: 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 155 DWARFContext& getContext() const { return Context; } 156 157 StringRef getLineSection() const { return LineSection; } 158 StringRef getStringSection() const { return StringSection; } 159 StringRef getStringOffsetSection() const { return StringOffsetSection; } 160 void setAddrOffsetSection(StringRef AOS, uint32_t Base) { 161 AddrOffsetSection = AOS; 162 AddrOffsetSectionBase = Base; 163 } 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 173 DataExtractor getDebugInfoExtractor() const { 174 return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize); 175 } 176 DataExtractor getStringExtractor() const { 177 return DataExtractor(StringSection, false, 0); 178 } 179 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(); 190 uint32_t getOffset() const { return Offset; } 191 uint32_t getNextUnitOffset() const { return Offset + Length + 4; } 192 uint32_t getLength() const { return Length; } 193 uint16_t getVersion() const { return Version; } 194 const DWARFAbbreviationDeclarationSet *getAbbreviations() const { 195 return Abbrevs; 196 } 197 uint8_t getAddressByteSize() const { return AddrSize; } 198 uint64_t getBaseAddress() const { return BaseAddr; } 199 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. 220 const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } 221 222 /// \brief Returns the number of DIEs in the unit. Parses the unit 223 /// if necessary. 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(). 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. 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. 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 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 268private: 269 /// Size in bytes of the .debug_info data associated with this compile unit. 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