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