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