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_DEBUGINFO_DWARF_DWARFUNIT_H 11 #define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H 12 13 #include "llvm/ADT/Optional.h" 14 #include "llvm/ADT/STLExtras.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/ADT/iterator_range.h" 18 #include "llvm/BinaryFormat/Dwarf.h" 19 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" 20 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" 21 #include "llvm/DebugInfo/DWARF/DWARFDie.h" 22 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 23 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" 24 #include "llvm/DebugInfo/DWARF/DWARFSection.h" 25 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" 26 #include "llvm/Support/DataExtractor.h" 27 #include <algorithm> 28 #include <cassert> 29 #include <cstddef> 30 #include <cstdint> 31 #include <map> 32 #include <memory> 33 #include <utility> 34 #include <vector> 35 36 namespace llvm { 37 38 class DWARFAbbreviationDeclarationSet; 39 class DWARFContext; 40 class DWARFDebugAbbrev; 41 class DWARFUnit; 42 43 /// Base class for all DWARFUnitSection classes. This provides the 44 /// functionality common to all unit types. 45 class DWARFUnitSectionBase { 46 public: 47 /// Returns the Unit that contains the given section offset in the 48 /// same section this Unit originated from. 49 virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; 50 virtual DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) = 0; 51 52 void parse(DWARFContext &C, const DWARFSection &Section); 53 void parseDWO(DWARFContext &C, const DWARFSection &DWOSection, 54 bool Lazy = false); 55 56 protected: 57 ~DWARFUnitSectionBase() = default; 58 59 virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section, 60 const DWARFDebugAbbrev *DA, const DWARFSection *RS, 61 StringRef SS, const DWARFSection &SOS, 62 const DWARFSection *AOS, const DWARFSection &LS, 63 bool isLittleEndian, bool isDWO, bool Lazy) = 0; 64 }; 65 66 const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, 67 DWARFSectionKind Kind); 68 69 /// Concrete instance of DWARFUnitSection, specialized for one Unit type. 70 template<typename UnitType> 71 class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>, 72 public DWARFUnitSectionBase { 73 bool Parsed = false; 74 std::function<std::unique_ptr<UnitType>(uint32_t)> Parser; 75 76 public: 77 using UnitVector = SmallVectorImpl<std::unique_ptr<UnitType>>; 78 using iterator = typename UnitVector::iterator; 79 using iterator_range = llvm::iterator_range<typename UnitVector::iterator>; 80 81 UnitType *getUnitForOffset(uint32_t Offset) const override { 82 auto *CU = std::upper_bound( 83 this->begin(), this->end(), Offset, 84 [](uint32_t LHS, const std::unique_ptr<UnitType> &RHS) { 85 return LHS < RHS->getNextUnitOffset(); 86 }); 87 if (CU != this->end() && (*CU)->getOffset() <= Offset) 88 return CU->get(); 89 return nullptr; 90 } 91 UnitType *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) override { 92 const auto *CUOff = E.getOffset(DW_SECT_INFO); 93 if (!CUOff) 94 return nullptr; 95 96 auto Offset = CUOff->Offset; 97 98 auto *CU = std::upper_bound( 99 this->begin(), this->end(), CUOff->Offset, 100 [](uint32_t LHS, const std::unique_ptr<UnitType> &RHS) { 101 return LHS < RHS->getNextUnitOffset(); 102 }); 103 if (CU != this->end() && (*CU)->getOffset() <= Offset) 104 return CU->get(); 105 106 if (!Parser) 107 return nullptr; 108 109 auto U = Parser(Offset); 110 if (!U) 111 U = nullptr; 112 113 auto *NewCU = U.get(); 114 this->insert(CU, std::move(U)); 115 return NewCU; 116 } 117 118 private: 119 void parseImpl(DWARFContext &Context, const DWARFSection &Section, 120 const DWARFDebugAbbrev *DA, const DWARFSection *RS, 121 StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, 122 const DWARFSection &LS, bool LE, bool IsDWO, 123 bool Lazy) override { 124 if (Parsed) 125 return; 126 DataExtractor Data(Section.Data, LE, 0); 127 if (!Parser) { 128 const DWARFUnitIndex *Index = nullptr; 129 if (IsDWO) 130 Index = &getDWARFUnitIndex(Context, UnitType::Section); 131 Parser = [=, &Context, &Section, &SOS, 132 &LS](uint32_t Offset) -> std::unique_ptr<UnitType> { 133 if (!Data.isValidOffset(Offset)) 134 return nullptr; 135 auto U = llvm::make_unique<UnitType>( 136 Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, *this, 137 Index ? Index->getFromOffset(Offset) : nullptr); 138 if (!U->extract(Data, &Offset)) 139 return nullptr; 140 return U; 141 }; 142 } 143 if (Lazy) 144 return; 145 auto I = this->begin(); 146 uint32_t Offset = 0; 147 while (Data.isValidOffset(Offset)) { 148 if (I != this->end() && (*I)->getOffset() == Offset) { 149 ++I; 150 continue; 151 } 152 auto U = Parser(Offset); 153 if (!U) 154 break; 155 Offset = U->getNextUnitOffset(); 156 I = std::next(this->insert(I, std::move(U))); 157 } 158 Parsed = true; 159 } 160 }; 161 162 /// Represents base address of the CU. 163 struct BaseAddress { 164 uint64_t Address; 165 uint64_t SectionIndex; 166 }; 167 168 class DWARFUnit { 169 DWARFContext &Context; 170 /// Section containing this DWARFUnit. 171 const DWARFSection &InfoSection; 172 173 const DWARFDebugAbbrev *Abbrev; 174 const DWARFSection *RangeSection; 175 uint32_t RangeSectionBase; 176 const DWARFSection &LineSection; 177 StringRef StringSection; 178 const DWARFSection &StringOffsetSection; 179 uint64_t StringOffsetSectionBase = 0; 180 const DWARFSection *AddrOffsetSection; 181 uint32_t AddrOffsetSectionBase = 0; 182 bool isLittleEndian; 183 bool isDWO; 184 const DWARFUnitSectionBase &UnitSection; 185 186 // Version, address size, and DWARF format. 187 DWARFFormParams FormParams; 188 189 uint32_t Offset; 190 uint32_t Length; 191 mutable const DWARFAbbreviationDeclarationSet *Abbrevs; 192 uint64_t AbbrOffset; 193 uint8_t UnitType; 194 llvm::Optional<BaseAddress> BaseAddr; 195 /// The compile unit debug information entry items. 196 std::vector<DWARFDebugInfoEntry> DieArray; 197 198 /// Map from range's start address to end address and corresponding DIE. 199 /// IntervalMap does not support range removal, as a result, we use the 200 /// std::map::upper_bound for address range lookup. 201 std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap; 202 203 using die_iterator_range = 204 iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>; 205 206 std::shared_ptr<DWARFUnit> DWO; 207 208 const DWARFUnitIndex::Entry *IndexEntry; 209 210 uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) { 211 auto First = DieArray.data(); 212 assert(Die >= First && Die < First + DieArray.size()); 213 return Die - First; 214 } 215 216 protected: 217 virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); 218 219 /// Size in bytes of the unit header. 220 virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; } 221 222 public: 223 DWARFUnit(DWARFContext &Context, const DWARFSection &Section, 224 const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, 225 const DWARFSection &SOS, const DWARFSection *AOS, 226 const DWARFSection &LS, bool LE, bool IsDWO, 227 const DWARFUnitSectionBase &UnitSection, 228 const DWARFUnitIndex::Entry *IndexEntry = nullptr); 229 230 virtual ~DWARFUnit(); 231 232 DWARFContext& getContext() const { return Context; } 233 234 const DWARFSection &getLineSection() const { return LineSection; } 235 StringRef getStringSection() const { return StringSection; } 236 const DWARFSection &getStringOffsetSection() const { 237 return StringOffsetSection; 238 } 239 240 void setAddrOffsetSection(const DWARFSection *AOS, uint32_t Base) { 241 AddrOffsetSection = AOS; 242 AddrOffsetSectionBase = Base; 243 } 244 245 /// Recursively update address to Die map. 246 void updateAddressDieMap(DWARFDie Die); 247 248 void setRangesSection(const DWARFSection *RS, uint32_t Base) { 249 RangeSection = RS; 250 RangeSectionBase = Base; 251 } 252 253 bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; 254 bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const; 255 256 DWARFDataExtractor getDebugInfoExtractor() const; 257 258 DataExtractor getStringExtractor() const { 259 return DataExtractor(StringSection, false, 0); 260 } 261 262 263 bool extract(DataExtractor debug_info, uint32_t* offset_ptr); 264 265 /// extractRangeList - extracts the range list referenced by this compile 266 /// unit from .debug_ranges section. Returns true on success. 267 /// Requires that compile unit is already extracted. 268 bool extractRangeList(uint32_t RangeListOffset, 269 DWARFDebugRangeList &RangeList) const; 270 void clear(); 271 uint32_t getOffset() const { return Offset; } 272 uint32_t getNextUnitOffset() const { return Offset + Length + 4; } 273 uint32_t getLength() const { return Length; } 274 275 const DWARFFormParams &getFormParams() const { return FormParams; } 276 uint16_t getVersion() const { return FormParams.Version; } 277 dwarf::DwarfFormat getFormat() const { return FormParams.Format; } 278 uint8_t getAddressByteSize() const { return FormParams.AddrSize; } 279 uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); } 280 uint8_t getDwarfOffsetByteSize() const { 281 return FormParams.getDwarfOffsetByteSize(); 282 } 283 284 const DWARFAbbreviationDeclarationSet *getAbbreviations() const; 285 286 uint8_t getUnitType() const { return UnitType; } 287 288 static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) { 289 switch (UnitType) { 290 case dwarf::DW_UT_compile: 291 return Tag == dwarf::DW_TAG_compile_unit; 292 case dwarf::DW_UT_type: 293 return Tag == dwarf::DW_TAG_type_unit; 294 case dwarf::DW_UT_partial: 295 return Tag == dwarf::DW_TAG_partial_unit; 296 case dwarf::DW_UT_skeleton: 297 return Tag == dwarf::DW_TAG_skeleton_unit; 298 case dwarf::DW_UT_split_compile: 299 case dwarf::DW_UT_split_type: 300 return dwarf::isUnitType(Tag); 301 } 302 return false; 303 } 304 305 /// \brief Return the number of bytes for the header of a unit of 306 /// UnitType type. 307 /// 308 /// This function must be called with a valid unit type which in 309 /// DWARF5 is defined as one of the following six types. 310 static uint32_t getDWARF5HeaderSize(uint8_t UnitType) { 311 switch (UnitType) { 312 case dwarf::DW_UT_compile: 313 case dwarf::DW_UT_partial: 314 return 12; 315 case dwarf::DW_UT_skeleton: 316 case dwarf::DW_UT_split_compile: 317 return 20; 318 case dwarf::DW_UT_type: 319 case dwarf::DW_UT_split_type: 320 return 24; 321 } 322 llvm_unreachable("Invalid UnitType."); 323 } 324 325 llvm::Optional<BaseAddress> getBaseAddress() const { return BaseAddr; } 326 327 void setBaseAddress(BaseAddress BaseAddr) { this->BaseAddr = BaseAddr; } 328 329 DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { 330 extractDIEsIfNeeded(ExtractUnitDIEOnly); 331 if (DieArray.empty()) 332 return DWARFDie(); 333 return DWARFDie(this, &DieArray[0]); 334 } 335 336 const char *getCompilationDir(); 337 Optional<uint64_t> getDWOId(); 338 339 void collectAddressRanges(DWARFAddressRangesVector &CURanges); 340 341 /// getInlinedChainForAddress - fetches inlined chain for a given address. 342 /// Returns empty chain if there is no subprogram containing address. The 343 /// chain is valid as long as parsed compile unit DIEs are not cleared. 344 void getInlinedChainForAddress(uint64_t Address, 345 SmallVectorImpl<DWARFDie> &InlinedChain); 346 347 /// getUnitSection - Return the DWARFUnitSection containing this unit. 348 const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } 349 350 /// \brief Returns the number of DIEs in the unit. Parses the unit 351 /// if necessary. 352 unsigned getNumDIEs() { 353 extractDIEsIfNeeded(false); 354 return DieArray.size(); 355 } 356 357 /// \brief Return the index of a DIE inside the unit's DIE vector. 358 /// 359 /// It is illegal to call this method with a DIE that hasn't be 360 /// created by this unit. In other word, it's illegal to call this 361 /// method on a DIE that isn't accessible by following 362 /// children/sibling links starting from this unit's getUnitDIE(). 363 uint32_t getDIEIndex(const DWARFDie &D) { 364 return getDIEIndex(D.getDebugInfoEntry()); 365 } 366 367 /// \brief Return the DIE object at the given index. 368 DWARFDie getDIEAtIndex(unsigned Index) { 369 assert(Index < DieArray.size()); 370 return DWARFDie(this, &DieArray[Index]); 371 } 372 373 DWARFDie getParent(const DWARFDebugInfoEntry *Die); 374 DWARFDie getSibling(const DWARFDebugInfoEntry *Die); 375 376 /// \brief Return the DIE object for a given offset inside the 377 /// unit's DIE vector. 378 /// 379 /// The unit needs to have its DIEs extracted for this method to work. 380 DWARFDie getDIEForOffset(uint32_t Offset) { 381 extractDIEsIfNeeded(false); 382 assert(!DieArray.empty()); 383 auto it = std::lower_bound( 384 DieArray.begin(), DieArray.end(), Offset, 385 [](const DWARFDebugInfoEntry &LHS, uint32_t Offset) { 386 return LHS.getOffset() < Offset; 387 }); 388 if (it != DieArray.end() && it->getOffset() == Offset) 389 return DWARFDie(this, &*it); 390 return DWARFDie(); 391 } 392 393 uint32_t getLineTableOffset() const { 394 if (IndexEntry) 395 if (const auto *Contrib = IndexEntry->getOffset(DW_SECT_LINE)) 396 return Contrib->Offset; 397 return 0; 398 } 399 400 die_iterator_range dies() { 401 extractDIEsIfNeeded(false); 402 return die_iterator_range(DieArray.begin(), DieArray.end()); 403 } 404 405 private: 406 /// Size in bytes of the .debug_info data associated with this compile unit. 407 size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } 408 409 /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it 410 /// hasn't already been done. Returns the number of DIEs parsed at this call. 411 size_t extractDIEsIfNeeded(bool CUDieOnly); 412 413 /// extractDIEsToVector - Appends all parsed DIEs to a vector. 414 void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, 415 std::vector<DWARFDebugInfoEntry> &DIEs) const; 416 417 /// clearDIEs - Clear parsed DIEs to keep memory usage low. 418 void clearDIEs(bool KeepCUDie); 419 420 /// parseDWO - Parses .dwo file for current compile unit. Returns true if 421 /// it was actually constructed. 422 bool parseDWO(); 423 424 /// getSubroutineForAddress - Returns subprogram DIE with address range 425 /// encompassing the provided address. The pointer is alive as long as parsed 426 /// compile unit DIEs are not cleared. 427 DWARFDie getSubroutineForAddress(uint64_t Address); 428 }; 429 430 } // end namespace llvm 431 432 #endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H 433