1 //===- DWARFContext.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_DWARFCONTEXT_H 11 #define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H 12 13 #include "llvm/ADT/MapVector.h" 14 #include "llvm/ADT/SmallString.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringMap.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/ADT/iterator_range.h" 19 #include "llvm/DebugInfo/DIContext.h" 20 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" 21 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 22 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 23 #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" 24 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 25 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 26 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 27 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" 28 #include "llvm/DebugInfo/DWARF/DWARFDie.h" 29 #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" 30 #include "llvm/DebugInfo/DWARF/DWARFObject.h" 31 #include "llvm/DebugInfo/DWARF/DWARFSection.h" 32 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" 33 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 34 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" 35 #include "llvm/Object/Binary.h" 36 #include "llvm/Object/ObjectFile.h" 37 #include "llvm/Support/DataExtractor.h" 38 #include "llvm/Support/Error.h" 39 #include "llvm/Support/Host.h" 40 #include <cstdint> 41 #include <deque> 42 #include <map> 43 #include <memory> 44 45 namespace llvm { 46 47 class MCRegisterInfo; 48 class MemoryBuffer; 49 class raw_ostream; 50 51 /// Used as a return value for a error callback passed to DWARF context. 52 /// Callback should return Halt if client application wants to stop 53 /// object parsing, or should return Continue otherwise. 54 enum class ErrorPolicy { Halt, Continue }; 55 56 /// DWARFContext 57 /// This data structure is the top level entity that deals with dwarf debug 58 /// information parsing. The actual data is supplied through DWARFObj. 59 class DWARFContext : public DIContext { 60 DWARFUnitSection<DWARFCompileUnit> CUs; 61 std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs; 62 std::unique_ptr<DWARFUnitIndex> CUIndex; 63 std::unique_ptr<DWARFGdbIndex> GdbIndex; 64 std::unique_ptr<DWARFUnitIndex> TUIndex; 65 std::unique_ptr<DWARFDebugAbbrev> Abbrev; 66 std::unique_ptr<DWARFDebugLoc> Loc; 67 std::unique_ptr<DWARFDebugAranges> Aranges; 68 std::unique_ptr<DWARFDebugLine> Line; 69 std::unique_ptr<DWARFDebugFrame> DebugFrame; 70 std::unique_ptr<DWARFDebugFrame> EHFrame; 71 std::unique_ptr<DWARFDebugMacro> Macro; 72 std::unique_ptr<DWARFDebugNames> Names; 73 std::unique_ptr<AppleAcceleratorTable> AppleNames; 74 std::unique_ptr<AppleAcceleratorTable> AppleTypes; 75 std::unique_ptr<AppleAcceleratorTable> AppleNamespaces; 76 std::unique_ptr<AppleAcceleratorTable> AppleObjC; 77 78 DWARFUnitSection<DWARFCompileUnit> DWOCUs; 79 std::deque<DWARFUnitSection<DWARFTypeUnit>> DWOTUs; 80 std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; 81 std::unique_ptr<DWARFDebugLocDWO> LocDWO; 82 83 /// The maximum DWARF version of all units. 84 unsigned MaxVersion = 0; 85 86 struct DWOFile { 87 object::OwningBinary<object::ObjectFile> File; 88 std::unique_ptr<DWARFContext> Context; 89 }; 90 StringMap<std::weak_ptr<DWOFile>> DWOFiles; 91 std::weak_ptr<DWOFile> DWP; 92 bool CheckedForDWP = false; 93 std::string DWPName; 94 95 std::unique_ptr<MCRegisterInfo> RegInfo; 96 97 /// Read compile units from the debug_info section (if necessary) 98 /// and store them in CUs. 99 void parseCompileUnits(); 100 101 /// Read type units from the debug_types sections (if necessary) 102 /// and store them in TUs. 103 void parseTypeUnits(); 104 105 /// Read compile units from the debug_info.dwo section (if necessary) 106 /// and store them in DWOCUs. 107 void parseDWOCompileUnits(); 108 109 /// Read type units from the debug_types.dwo section (if necessary) 110 /// and store them in DWOTUs. 111 void parseDWOTypeUnits(); 112 113 protected: 114 std::unique_ptr<const DWARFObject> DObj; 115 116 public: 117 DWARFContext(std::unique_ptr<const DWARFObject> DObj, 118 std::string DWPName = ""); 119 ~DWARFContext(); 120 121 DWARFContext(DWARFContext &) = delete; 122 DWARFContext &operator=(DWARFContext &) = delete; 123 getDWARFObj()124 const DWARFObject &getDWARFObj() const { return *DObj; } 125 classof(const DIContext * DICtx)126 static bool classof(const DIContext *DICtx) { 127 return DICtx->getKind() == CK_DWARF; 128 } 129 130 /// Dump a textual representation to \p OS. If any \p DumpOffsets are present, 131 /// dump only the record at the specified offset. 132 void dump(raw_ostream &OS, DIDumpOptions DumpOpts, 133 std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets); 134 dump(raw_ostream & OS,DIDumpOptions DumpOpts)135 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override { 136 std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets; 137 dump(OS, DumpOpts, DumpOffsets); 138 } 139 140 bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; 141 142 using cu_iterator_range = DWARFUnitSection<DWARFCompileUnit>::iterator_range; 143 using tu_iterator_range = DWARFUnitSection<DWARFTypeUnit>::iterator_range; 144 using tu_section_iterator_range = iterator_range<decltype(TUs)::iterator>; 145 146 /// Get compile units in this context. compile_units()147 cu_iterator_range compile_units() { 148 parseCompileUnits(); 149 return cu_iterator_range(CUs.begin(), CUs.end()); 150 } 151 152 /// Get type units in this context. type_unit_sections()153 tu_section_iterator_range type_unit_sections() { 154 parseTypeUnits(); 155 return tu_section_iterator_range(TUs.begin(), TUs.end()); 156 } 157 158 /// Get compile units in the DWO context. dwo_compile_units()159 cu_iterator_range dwo_compile_units() { 160 parseDWOCompileUnits(); 161 return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); 162 } 163 164 /// Get type units in the DWO context. dwo_type_unit_sections()165 tu_section_iterator_range dwo_type_unit_sections() { 166 parseDWOTypeUnits(); 167 return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end()); 168 } 169 170 /// Get the number of compile units in this context. getNumCompileUnits()171 unsigned getNumCompileUnits() { 172 parseCompileUnits(); 173 return CUs.size(); 174 } 175 176 /// Get the number of compile units in this context. getNumTypeUnits()177 unsigned getNumTypeUnits() { 178 parseTypeUnits(); 179 return TUs.size(); 180 } 181 182 /// Get the number of compile units in the DWO context. getNumDWOCompileUnits()183 unsigned getNumDWOCompileUnits() { 184 parseDWOCompileUnits(); 185 return DWOCUs.size(); 186 } 187 188 /// Get the number of compile units in the DWO context. getNumDWOTypeUnits()189 unsigned getNumDWOTypeUnits() { 190 parseDWOTypeUnits(); 191 return DWOTUs.size(); 192 } 193 194 /// Get the compile unit at the specified index for this compile unit. getCompileUnitAtIndex(unsigned index)195 DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { 196 parseCompileUnits(); 197 return CUs[index].get(); 198 } 199 200 /// Get the compile unit at the specified index for the DWO compile units. getDWOCompileUnitAtIndex(unsigned index)201 DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { 202 parseDWOCompileUnits(); 203 return DWOCUs[index].get(); 204 } 205 206 DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); 207 208 /// Return the compile unit that includes an offset (relative to .debug_info). 209 DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); 210 211 /// Get a DIE given an exact offset. 212 DWARFDie getDIEForOffset(uint32_t Offset); 213 getMaxVersion()214 unsigned getMaxVersion() const { return MaxVersion; } 215 setMaxVersionIfGreater(unsigned Version)216 void setMaxVersionIfGreater(unsigned Version) { 217 if (Version > MaxVersion) 218 MaxVersion = Version; 219 } 220 221 const DWARFUnitIndex &getCUIndex(); 222 DWARFGdbIndex &getGdbIndex(); 223 const DWARFUnitIndex &getTUIndex(); 224 225 /// Get a pointer to the parsed DebugAbbrev object. 226 const DWARFDebugAbbrev *getDebugAbbrev(); 227 228 /// Get a pointer to the parsed DebugLoc object. 229 const DWARFDebugLoc *getDebugLoc(); 230 231 /// Get a pointer to the parsed dwo abbreviations object. 232 const DWARFDebugAbbrev *getDebugAbbrevDWO(); 233 234 /// Get a pointer to the parsed DebugLoc object. 235 const DWARFDebugLocDWO *getDebugLocDWO(); 236 237 /// Get a pointer to the parsed DebugAranges object. 238 const DWARFDebugAranges *getDebugAranges(); 239 240 /// Get a pointer to the parsed frame information object. 241 const DWARFDebugFrame *getDebugFrame(); 242 243 /// Get a pointer to the parsed eh frame information object. 244 const DWARFDebugFrame *getEHFrame(); 245 246 /// Get a pointer to the parsed DebugMacro object. 247 const DWARFDebugMacro *getDebugMacro(); 248 249 /// Get a reference to the parsed accelerator table object. 250 const DWARFDebugNames &getDebugNames(); 251 252 /// Get a reference to the parsed accelerator table object. 253 const AppleAcceleratorTable &getAppleNames(); 254 255 /// Get a reference to the parsed accelerator table object. 256 const AppleAcceleratorTable &getAppleTypes(); 257 258 /// Get a reference to the parsed accelerator table object. 259 const AppleAcceleratorTable &getAppleNamespaces(); 260 261 /// Get a reference to the parsed accelerator table object. 262 const AppleAcceleratorTable &getAppleObjC(); 263 264 /// Get a pointer to a parsed line table corresponding to a compile unit. 265 /// Report any parsing issues as warnings on stderr. 266 const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U); 267 268 /// Get a pointer to a parsed line table corresponding to a compile unit. 269 /// Report any recoverable parsing problems using the callback. 270 Expected<const DWARFDebugLine::LineTable *> 271 getLineTableForUnit(DWARFUnit *U, 272 std::function<void(Error)> RecoverableErrorCallback); 273 getStringExtractor()274 DataExtractor getStringExtractor() const { 275 return DataExtractor(DObj->getStringSection(), false, 0); 276 } getLineStringExtractor()277 DataExtractor getLineStringExtractor() const { 278 return DataExtractor(DObj->getLineStringSection(), false, 0); 279 } 280 281 /// Wraps the returned DIEs for a given address. 282 struct DIEsForAddress { 283 DWARFCompileUnit *CompileUnit = nullptr; 284 DWARFDie FunctionDIE; 285 DWARFDie BlockDIE; 286 explicit operator bool() const { return CompileUnit != nullptr; } 287 }; 288 289 /// Get the compilation unit, the function DIE and lexical block DIE for the 290 /// given address where applicable. 291 DIEsForAddress getDIEsForAddress(uint64_t Address); 292 293 DILineInfo getLineInfoForAddress(uint64_t Address, 294 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; 295 DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, 296 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; 297 DIInliningInfo getInliningInfoForAddress(uint64_t Address, 298 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; 299 isLittleEndian()300 bool isLittleEndian() const { return DObj->isLittleEndian(); } isSupportedVersion(unsigned version)301 static bool isSupportedVersion(unsigned version) { 302 return version == 2 || version == 3 || version == 4 || version == 5; 303 } 304 305 std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath); 306 getRegisterInfo()307 const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); } 308 309 /// Function used to handle default error reporting policy. Prints a error 310 /// message and returns Continue, so DWARF context ignores the error. 311 static ErrorPolicy defaultErrorHandler(Error E); 312 static std::unique_ptr<DWARFContext> 313 create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, 314 function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler, 315 std::string DWPName = ""); 316 317 static std::unique_ptr<DWARFContext> 318 create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, 319 uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost); 320 321 /// Loads register info for the architecture of the provided object file. 322 /// Improves readability of dumped DWARF expressions. Requires the caller to 323 /// have initialized the relevant target descriptions. 324 Error loadRegisterInfo(const object::ObjectFile &Obj); 325 326 /// Get address size from CUs. 327 /// TODO: refactor compile_units() to make this const. 328 uint8_t getCUAddrSize(); 329 330 private: 331 /// Return the compile unit which contains instruction with provided 332 /// address. 333 DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); 334 }; 335 336 } // end namespace llvm 337 338 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H 339