1 //===- DWARFContext.h -------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===/ 8 9 #ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H 10 #define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H 11 12 #include "llvm/ADT/SmallVector.h" 13 #include "llvm/ADT/StringMap.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/DebugInfo/DIContext.h" 16 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 17 #include "llvm/DebugInfo/DWARF/DWARFDie.h" 18 #include "llvm/DebugInfo/DWARF/DWARFObject.h" 19 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 20 #include "llvm/Object/Binary.h" 21 #include "llvm/Object/ObjectFile.h" 22 #include "llvm/Support/DataExtractor.h" 23 #include "llvm/Support/Error.h" 24 #include "llvm/Support/Host.h" 25 #include <cstdint> 26 #include <memory> 27 28 namespace llvm { 29 30 class MemoryBuffer; 31 class AppleAcceleratorTable; 32 class DWARFCompileUnit; 33 class DWARFDebugAbbrev; 34 class DWARFDebugAranges; 35 class DWARFDebugFrame; 36 class DWARFDebugLoc; 37 class DWARFDebugMacro; 38 class DWARFDebugNames; 39 class DWARFGdbIndex; 40 class DWARFTypeUnit; 41 class DWARFUnitIndex; 42 43 /// DWARFContext 44 /// This data structure is the top level entity that deals with dwarf debug 45 /// information parsing. The actual data is supplied through DWARFObj. 46 class DWARFContext : public DIContext { 47 DWARFUnitVector NormalUnits; 48 std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> NormalTypeUnits; 49 std::unique_ptr<DWARFUnitIndex> CUIndex; 50 std::unique_ptr<DWARFGdbIndex> GdbIndex; 51 std::unique_ptr<DWARFUnitIndex> TUIndex; 52 std::unique_ptr<DWARFDebugAbbrev> Abbrev; 53 std::unique_ptr<DWARFDebugLoc> Loc; 54 std::unique_ptr<DWARFDebugAranges> Aranges; 55 std::unique_ptr<DWARFDebugLine> Line; 56 std::unique_ptr<DWARFDebugFrame> DebugFrame; 57 std::unique_ptr<DWARFDebugFrame> EHFrame; 58 std::unique_ptr<DWARFDebugMacro> Macro; 59 std::unique_ptr<DWARFDebugMacro> Macinfo; 60 std::unique_ptr<DWARFDebugNames> Names; 61 std::unique_ptr<AppleAcceleratorTable> AppleNames; 62 std::unique_ptr<AppleAcceleratorTable> AppleTypes; 63 std::unique_ptr<AppleAcceleratorTable> AppleNamespaces; 64 std::unique_ptr<AppleAcceleratorTable> AppleObjC; 65 66 DWARFUnitVector DWOUnits; 67 std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> DWOTypeUnits; 68 std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; 69 std::unique_ptr<DWARFDebugMacro> MacinfoDWO; 70 std::unique_ptr<DWARFDebugMacro> MacroDWO; 71 72 /// The maximum DWARF version of all units. 73 unsigned MaxVersion = 0; 74 75 struct DWOFile { 76 object::OwningBinary<object::ObjectFile> File; 77 std::unique_ptr<DWARFContext> Context; 78 }; 79 StringMap<std::weak_ptr<DWOFile>> DWOFiles; 80 std::weak_ptr<DWOFile> DWP; 81 bool CheckedForDWP = false; 82 std::string DWPName; 83 std::function<void(Error)> RecoverableErrorHandler = 84 WithColor::defaultErrorHandler; 85 std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler; 86 87 /// Read compile units from the debug_info section (if necessary) 88 /// and type units from the debug_types sections (if necessary) 89 /// and store them in NormalUnits. 90 void parseNormalUnits(); 91 92 /// Read compile units from the debug_info.dwo section (if necessary) 93 /// and type units from the debug_types.dwo section (if necessary) 94 /// and store them in DWOUnits. 95 /// If \p Lazy is true, set up to parse but don't actually parse them. 96 enum { EagerParse = false, LazyParse = true }; 97 void parseDWOUnits(bool Lazy = false); 98 99 std::unique_ptr<const DWARFObject> DObj; 100 101 /// Helper enum to distinguish between macro[.dwo] and macinfo[.dwo] 102 /// section. 103 enum MacroSecType { 104 MacinfoSection, 105 MacinfoDwoSection, 106 MacroSection, 107 MacroDwoSection 108 }; 109 110 // When set parses debug_info.dwo/debug_abbrev.dwo manually and populates CU 111 // Index, and TU Index for DWARF5. 112 bool ParseCUTUIndexManually = false; 113 114 public: 115 DWARFContext(std::unique_ptr<const DWARFObject> DObj, 116 std::string DWPName = "", 117 std::function<void(Error)> RecoverableErrorHandler = 118 WithColor::defaultErrorHandler, 119 std::function<void(Error)> WarningHandler = 120 WithColor::defaultWarningHandler); 121 ~DWARFContext() override; 122 123 DWARFContext(DWARFContext &) = delete; 124 DWARFContext &operator=(DWARFContext &) = delete; 125 getDWARFObj()126 const DWARFObject &getDWARFObj() const { return *DObj; } 127 classof(const DIContext * DICtx)128 static bool classof(const DIContext *DICtx) { 129 return DICtx->getKind() == CK_DWARF; 130 } 131 132 /// Dump a textual representation to \p OS. If any \p DumpOffsets are present, 133 /// dump only the record at the specified offset. 134 void dump(raw_ostream &OS, DIDumpOptions DumpOpts, 135 std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets); 136 dump(raw_ostream & OS,DIDumpOptions DumpOpts)137 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override { 138 std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets; 139 dump(OS, DumpOpts, DumpOffsets); 140 } 141 142 bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; 143 144 using unit_iterator_range = DWARFUnitVector::iterator_range; 145 using compile_unit_range = DWARFUnitVector::compile_unit_range; 146 147 /// Get units from .debug_info in this context. info_section_units()148 unit_iterator_range info_section_units() { 149 parseNormalUnits(); 150 return unit_iterator_range(NormalUnits.begin(), 151 NormalUnits.begin() + 152 NormalUnits.getNumInfoUnits()); 153 } 154 getNormalUnitsVector()155 const DWARFUnitVector &getNormalUnitsVector() { 156 parseNormalUnits(); 157 return NormalUnits; 158 } 159 160 /// Get units from .debug_types in this context. types_section_units()161 unit_iterator_range types_section_units() { 162 parseNormalUnits(); 163 return unit_iterator_range( 164 NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end()); 165 } 166 167 /// Get compile units in this context. compile_units()168 compile_unit_range compile_units() { 169 return make_filter_range(info_section_units(), isCompileUnit); 170 } 171 172 // If you want type_units(), it'll need to be a concat iterator of a filter of 173 // TUs in info_section + all the (all type) units in types_section 174 175 /// Get all normal compile/type units in this context. normal_units()176 unit_iterator_range normal_units() { 177 parseNormalUnits(); 178 return unit_iterator_range(NormalUnits.begin(), NormalUnits.end()); 179 } 180 181 /// Get units from .debug_info..dwo in the DWO context. dwo_info_section_units()182 unit_iterator_range dwo_info_section_units() { 183 parseDWOUnits(); 184 return unit_iterator_range(DWOUnits.begin(), 185 DWOUnits.begin() + DWOUnits.getNumInfoUnits()); 186 } 187 getDWOUnitsVector()188 const DWARFUnitVector &getDWOUnitsVector() { 189 parseDWOUnits(); 190 return DWOUnits; 191 } 192 193 /// Get units from .debug_types.dwo in the DWO context. dwo_types_section_units()194 unit_iterator_range dwo_types_section_units() { 195 parseDWOUnits(); 196 return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(), 197 DWOUnits.end()); 198 } 199 200 /// Get compile units in the DWO context. dwo_compile_units()201 compile_unit_range dwo_compile_units() { 202 return make_filter_range(dwo_info_section_units(), isCompileUnit); 203 } 204 205 // If you want dwo_type_units(), it'll need to be a concat iterator of a 206 // filter of TUs in dwo_info_section + all the (all type) units in 207 // dwo_types_section. 208 209 /// Get all units in the DWO context. dwo_units()210 unit_iterator_range dwo_units() { 211 parseDWOUnits(); 212 return unit_iterator_range(DWOUnits.begin(), DWOUnits.end()); 213 } 214 215 /// Get the number of compile units in this context. getNumCompileUnits()216 unsigned getNumCompileUnits() { 217 parseNormalUnits(); 218 return NormalUnits.getNumInfoUnits(); 219 } 220 221 /// Get the number of type units in this context. getNumTypeUnits()222 unsigned getNumTypeUnits() { 223 parseNormalUnits(); 224 return NormalUnits.getNumTypesUnits(); 225 } 226 227 /// Get the number of compile units in the DWO context. getNumDWOCompileUnits()228 unsigned getNumDWOCompileUnits() { 229 parseDWOUnits(); 230 return DWOUnits.getNumInfoUnits(); 231 } 232 233 /// Get the number of type units in the DWO context. getNumDWOTypeUnits()234 unsigned getNumDWOTypeUnits() { 235 parseDWOUnits(); 236 return DWOUnits.getNumTypesUnits(); 237 } 238 239 /// Get the unit at the specified index. getUnitAtIndex(unsigned index)240 DWARFUnit *getUnitAtIndex(unsigned index) { 241 parseNormalUnits(); 242 return NormalUnits[index].get(); 243 } 244 245 /// Get the unit at the specified index for the DWO units. getDWOUnitAtIndex(unsigned index)246 DWARFUnit *getDWOUnitAtIndex(unsigned index) { 247 parseDWOUnits(); 248 return DWOUnits[index].get(); 249 } 250 251 DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); 252 DWARFTypeUnit *getTypeUnitForHash(uint16_t Version, uint64_t Hash, bool IsDWO); 253 254 /// Return the compile unit that includes an offset (relative to .debug_info). 255 DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset); 256 257 /// Get a DIE given an exact offset. 258 DWARFDie getDIEForOffset(uint64_t Offset); 259 getMaxVersion()260 unsigned getMaxVersion() { 261 // Ensure info units have been parsed to discover MaxVersion 262 info_section_units(); 263 return MaxVersion; 264 } 265 getMaxDWOVersion()266 unsigned getMaxDWOVersion() { 267 // Ensure DWO info units have been parsed to discover MaxVersion 268 dwo_info_section_units(); 269 return MaxVersion; 270 } 271 setMaxVersionIfGreater(unsigned Version)272 void setMaxVersionIfGreater(unsigned Version) { 273 if (Version > MaxVersion) 274 MaxVersion = Version; 275 } 276 277 const DWARFUnitIndex &getCUIndex(); 278 DWARFGdbIndex &getGdbIndex(); 279 const DWARFUnitIndex &getTUIndex(); 280 281 /// Get a pointer to the parsed DebugAbbrev object. 282 const DWARFDebugAbbrev *getDebugAbbrev(); 283 284 /// Get a pointer to the parsed DebugLoc object. 285 const DWARFDebugLoc *getDebugLoc(); 286 287 /// Get a pointer to the parsed dwo abbreviations object. 288 const DWARFDebugAbbrev *getDebugAbbrevDWO(); 289 290 /// Get a pointer to the parsed DebugAranges object. 291 const DWARFDebugAranges *getDebugAranges(); 292 293 /// Get a pointer to the parsed frame information object. 294 Expected<const DWARFDebugFrame *> getDebugFrame(); 295 296 /// Get a pointer to the parsed eh frame information object. 297 Expected<const DWARFDebugFrame *> getEHFrame(); 298 299 /// Get a pointer to the parsed DebugMacinfo information object. 300 const DWARFDebugMacro *getDebugMacinfo(); 301 302 /// Get a pointer to the parsed DebugMacinfoDWO information object. 303 const DWARFDebugMacro *getDebugMacinfoDWO(); 304 305 /// Get a pointer to the parsed DebugMacro information object. 306 const DWARFDebugMacro *getDebugMacro(); 307 308 /// Get a pointer to the parsed DebugMacroDWO information object. 309 const DWARFDebugMacro *getDebugMacroDWO(); 310 311 /// Get a reference to the parsed accelerator table object. 312 const DWARFDebugNames &getDebugNames(); 313 314 /// Get a reference to the parsed accelerator table object. 315 const AppleAcceleratorTable &getAppleNames(); 316 317 /// Get a reference to the parsed accelerator table object. 318 const AppleAcceleratorTable &getAppleTypes(); 319 320 /// Get a reference to the parsed accelerator table object. 321 const AppleAcceleratorTable &getAppleNamespaces(); 322 323 /// Get a reference to the parsed accelerator table object. 324 const AppleAcceleratorTable &getAppleObjC(); 325 326 /// Get a pointer to a parsed line table corresponding to a compile unit. 327 /// Report any parsing issues as warnings on stderr. 328 const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U); 329 330 /// Get a pointer to a parsed line table corresponding to a compile unit. 331 /// Report any recoverable parsing problems using the handler. 332 Expected<const DWARFDebugLine::LineTable *> 333 getLineTableForUnit(DWARFUnit *U, 334 function_ref<void(Error)> RecoverableErrorHandler); 335 336 // Clear the line table object corresponding to a compile unit for memory 337 // management purpose. When it's referred to again, it'll be re-populated. 338 void clearLineTableForUnit(DWARFUnit *U); 339 getStringExtractor()340 DataExtractor getStringExtractor() const { 341 return DataExtractor(DObj->getStrSection(), false, 0); 342 } getStringDWOExtractor()343 DataExtractor getStringDWOExtractor() const { 344 return DataExtractor(DObj->getStrDWOSection(), false, 0); 345 } getLineStringExtractor()346 DataExtractor getLineStringExtractor() const { 347 return DataExtractor(DObj->getLineStrSection(), false, 0); 348 } 349 350 /// Wraps the returned DIEs for a given address. 351 struct DIEsForAddress { 352 DWARFCompileUnit *CompileUnit = nullptr; 353 DWARFDie FunctionDIE; 354 DWARFDie BlockDIE; 355 explicit operator bool() const { return CompileUnit != nullptr; } 356 }; 357 358 /// Get the compilation unit, the function DIE and lexical block DIE for the 359 /// given address where applicable. 360 /// TODO: change input parameter from "uint64_t Address" 361 /// into "SectionedAddress Address" 362 DIEsForAddress getDIEsForAddress(uint64_t Address); 363 364 DILineInfo getLineInfoForAddress( 365 object::SectionedAddress Address, 366 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; 367 DILineInfo 368 getLineInfoForDataAddress(object::SectionedAddress Address) override; 369 DILineInfoTable getLineInfoForAddressRange( 370 object::SectionedAddress Address, uint64_t Size, 371 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; 372 DIInliningInfo getInliningInfoForAddress( 373 object::SectionedAddress Address, 374 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; 375 376 std::vector<DILocal> 377 getLocalsForAddress(object::SectionedAddress Address) override; 378 isLittleEndian()379 bool isLittleEndian() const { return DObj->isLittleEndian(); } getMaxSupportedVersion()380 static unsigned getMaxSupportedVersion() { return 5; } isSupportedVersion(unsigned version)381 static bool isSupportedVersion(unsigned version) { 382 return version >= 2 && version <= getMaxSupportedVersion(); 383 } 384 getSupportedAddressSizes()385 static SmallVector<uint8_t, 3> getSupportedAddressSizes() { 386 return {2, 4, 8}; 387 } isAddressSizeSupported(unsigned AddressSize)388 static bool isAddressSizeSupported(unsigned AddressSize) { 389 return llvm::is_contained(getSupportedAddressSizes(), AddressSize); 390 } 391 template <typename... Ts> checkAddressSizeSupported(unsigned AddressSize,std::error_code EC,char const * Fmt,const Ts &...Vals)392 static Error checkAddressSizeSupported(unsigned AddressSize, 393 std::error_code EC, char const *Fmt, 394 const Ts &...Vals) { 395 if (isAddressSizeSupported(AddressSize)) 396 return Error::success(); 397 std::string Buffer; 398 raw_string_ostream Stream(Buffer); 399 Stream << format(Fmt, Vals...) 400 << " has unsupported address size: " << AddressSize 401 << " (supported are "; 402 ListSeparator LS; 403 for (unsigned Size : DWARFContext::getSupportedAddressSizes()) 404 Stream << LS << Size; 405 Stream << ')'; 406 return make_error<StringError>(Stream.str(), EC); 407 } 408 409 std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath); 410 getRecoverableErrorHandler()411 function_ref<void(Error)> getRecoverableErrorHandler() { 412 return RecoverableErrorHandler; 413 } 414 getWarningHandler()415 function_ref<void(Error)> getWarningHandler() { return WarningHandler; } 416 417 enum class ProcessDebugRelocations { Process, Ignore }; 418 419 static std::unique_ptr<DWARFContext> 420 create(const object::ObjectFile &Obj, 421 ProcessDebugRelocations RelocAction = ProcessDebugRelocations::Process, 422 const LoadedObjectInfo *L = nullptr, std::string DWPName = "", 423 std::function<void(Error)> RecoverableErrorHandler = 424 WithColor::defaultErrorHandler, 425 std::function<void(Error)> WarningHandler = 426 WithColor::defaultWarningHandler); 427 428 static std::unique_ptr<DWARFContext> 429 create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, 430 uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost, 431 std::function<void(Error)> RecoverableErrorHandler = 432 WithColor::defaultErrorHandler, 433 std::function<void(Error)> WarningHandler = 434 WithColor::defaultWarningHandler); 435 436 /// Get address size from CUs. 437 /// TODO: refactor compile_units() to make this const. 438 uint8_t getCUAddrSize(); 439 getArch()440 Triple::ArchType getArch() const { 441 return getDWARFObj().getFile()->getArch(); 442 } 443 444 /// Return the compile unit which contains instruction with provided 445 /// address. 446 /// TODO: change input parameter from "uint64_t Address" 447 /// into "SectionedAddress Address" 448 DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); 449 450 /// Returns whether CU/TU should be populated manually. TU Index populated 451 /// manually only for DWARF5. getParseCUTUIndexManually()452 bool getParseCUTUIndexManually() const { return ParseCUTUIndexManually; } 453 454 /// Sets whether CU/TU should be populated manually. TU Index populated 455 /// manually only for DWARF5. setParseCUTUIndexManually(bool PCUTU)456 void setParseCUTUIndexManually(bool PCUTU) { ParseCUTUIndexManually = PCUTU; } 457 458 private: 459 /// Parse a macro[.dwo] or macinfo[.dwo] section. 460 std::unique_ptr<DWARFDebugMacro> 461 parseMacroOrMacinfo(MacroSecType SectionType); 462 463 void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die, 464 std::vector<DILocal> &Result); 465 }; 466 467 } // end namespace llvm 468 469 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H 470