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