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 MCRegisterInfo; 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 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 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 85 std::unique_ptr<MCRegisterInfo> RegInfo; 86 87 std::function<void(Error)> RecoverableErrorHandler = 88 WithColor::defaultErrorHandler; 89 std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler; 90 91 /// Read compile units from the debug_info section (if necessary) 92 /// and type units from the debug_types sections (if necessary) 93 /// and store them in NormalUnits. 94 void parseNormalUnits(); 95 96 /// Read compile units from the debug_info.dwo section (if necessary) 97 /// and type units from the debug_types.dwo section (if necessary) 98 /// and store them in DWOUnits. 99 /// If \p Lazy is true, set up to parse but don't actually parse them. 100 enum { EagerParse = false, LazyParse = true }; 101 void parseDWOUnits(bool Lazy = false); 102 103 std::unique_ptr<const DWARFObject> DObj; 104 105 /// Helper enum to distinguish between macro[.dwo] and macinfo[.dwo] 106 /// section. 107 enum MacroSecType { 108 MacinfoSection, 109 MacinfoDwoSection, 110 MacroSection, 111 MacroDwoSection 112 }; 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 126 const DWARFObject &getDWARFObj() const { return *DObj; } 127 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<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets); 136 137 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override { 138 std::array<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. 148 unit_iterator_range info_section_units() { 149 parseNormalUnits(); 150 return unit_iterator_range(NormalUnits.begin(), 151 NormalUnits.begin() + 152 NormalUnits.getNumInfoUnits()); 153 } 154 155 const DWARFUnitVector &getNormalUnitsVector() { 156 parseNormalUnits(); 157 return NormalUnits; 158 } 159 160 /// Get units from .debug_types in this context. 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. 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. 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. 182 unit_iterator_range dwo_info_section_units() { 183 parseDWOUnits(); 184 return unit_iterator_range(DWOUnits.begin(), 185 DWOUnits.begin() + DWOUnits.getNumInfoUnits()); 186 } 187 188 const DWARFUnitVector &getDWOUnitsVector() { 189 parseDWOUnits(); 190 return DWOUnits; 191 } 192 193 /// Get units from .debug_types.dwo in the DWO context. 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. 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. 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. 216 unsigned getNumCompileUnits() { 217 parseNormalUnits(); 218 return NormalUnits.getNumInfoUnits(); 219 } 220 221 /// Get the number of type units in this context. 222 unsigned getNumTypeUnits() { 223 parseNormalUnits(); 224 return NormalUnits.getNumTypesUnits(); 225 } 226 227 /// Get the number of compile units in the DWO context. 228 unsigned getNumDWOCompileUnits() { 229 parseDWOUnits(); 230 return DWOUnits.getNumInfoUnits(); 231 } 232 233 /// Get the number of type units in the DWO context. 234 unsigned getNumDWOTypeUnits() { 235 parseDWOUnits(); 236 return DWOUnits.getNumTypesUnits(); 237 } 238 239 /// Get the unit at the specified 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. 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 260 unsigned getMaxVersion() { 261 // Ensure info units have been parsed to discover MaxVersion 262 info_section_units(); 263 return MaxVersion; 264 } 265 266 unsigned getMaxDWOVersion() { 267 // Ensure DWO info units have been parsed to discover MaxVersion 268 dwo_info_section_units(); 269 return MaxVersion; 270 } 271 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 340 DataExtractor getStringExtractor() const { 341 return DataExtractor(DObj->getStrSection(), false, 0); 342 } 343 DataExtractor getStringDWOExtractor() const { 344 return DataExtractor(DObj->getStrDWOSection(), false, 0); 345 } 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 379 bool isLittleEndian() const { return DObj->isLittleEndian(); } 380 static unsigned getMaxSupportedVersion() { return 5; } 381 static bool isSupportedVersion(unsigned version) { 382 return version >= 2 && version <= getMaxSupportedVersion(); 383 } 384 385 static SmallVector<uint8_t, 3> getSupportedAddressSizes() { 386 return {2, 4, 8}; 387 } 388 static bool isAddressSizeSupported(unsigned AddressSize) { 389 return llvm::is_contained(getSupportedAddressSizes(), AddressSize); 390 } 391 template <typename... Ts> 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 411 const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); } 412 413 function_ref<void(Error)> getRecoverableErrorHandler() { 414 return RecoverableErrorHandler; 415 } 416 417 function_ref<void(Error)> getWarningHandler() { return WarningHandler; } 418 419 enum class ProcessDebugRelocations { Process, Ignore }; 420 421 static std::unique_ptr<DWARFContext> 422 create(const object::ObjectFile &Obj, 423 ProcessDebugRelocations RelocAction = ProcessDebugRelocations::Process, 424 const LoadedObjectInfo *L = nullptr, std::string DWPName = "", 425 std::function<void(Error)> RecoverableErrorHandler = 426 WithColor::defaultErrorHandler, 427 std::function<void(Error)> WarningHandler = 428 WithColor::defaultWarningHandler); 429 430 static std::unique_ptr<DWARFContext> 431 create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, 432 uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost, 433 std::function<void(Error)> RecoverableErrorHandler = 434 WithColor::defaultErrorHandler, 435 std::function<void(Error)> WarningHandler = 436 WithColor::defaultWarningHandler); 437 438 /// Loads register info for the architecture of the provided object file. 439 /// Improves readability of dumped DWARF expressions. Requires the caller to 440 /// have initialized the relevant target descriptions. 441 Error loadRegisterInfo(const object::ObjectFile &Obj); 442 443 /// Get address size from CUs. 444 /// TODO: refactor compile_units() to make this const. 445 uint8_t getCUAddrSize(); 446 447 Triple::ArchType getArch() const { 448 return getDWARFObj().getFile()->getArch(); 449 } 450 451 /// Return the compile unit which contains instruction with provided 452 /// address. 453 /// TODO: change input parameter from "uint64_t Address" 454 /// into "SectionedAddress Address" 455 DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); 456 457 private: 458 /// Parse a macro[.dwo] or macinfo[.dwo] section. 459 std::unique_ptr<DWARFDebugMacro> 460 parseMacroOrMacinfo(MacroSecType SectionType); 461 462 void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die, 463 std::vector<DILocal> &Result); 464 }; 465 466 } // end namespace llvm 467 468 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H 469