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