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 /// Used as a return value for a error callback passed to DWARF context. 51 /// Callback should return Halt if client application wants to stop 52 /// object parsing, or should return Continue otherwise. 53 enum class ErrorPolicy { Halt, Continue }; 54 55 /// DWARFContext 56 /// This data structure is the top level entity that deals with dwarf debug 57 /// information parsing. The actual data is supplied through DWARFObj. 58 class DWARFContext : public DIContext { 59 DWARFUnitVector NormalUnits; 60 std::unique_ptr<DWARFUnitIndex> CUIndex; 61 std::unique_ptr<DWARFGdbIndex> GdbIndex; 62 std::unique_ptr<DWARFUnitIndex> TUIndex; 63 std::unique_ptr<DWARFDebugAbbrev> Abbrev; 64 std::unique_ptr<DWARFDebugLoc> Loc; 65 std::unique_ptr<DWARFDebugAranges> Aranges; 66 std::unique_ptr<DWARFDebugLine> Line; 67 std::unique_ptr<DWARFDebugFrame> DebugFrame; 68 std::unique_ptr<DWARFDebugFrame> EHFrame; 69 std::unique_ptr<DWARFDebugMacro> Macro; 70 std::unique_ptr<DWARFDebugNames> Names; 71 std::unique_ptr<AppleAcceleratorTable> AppleNames; 72 std::unique_ptr<AppleAcceleratorTable> AppleTypes; 73 std::unique_ptr<AppleAcceleratorTable> AppleNamespaces; 74 std::unique_ptr<AppleAcceleratorTable> AppleObjC; 75 76 DWARFUnitVector DWOUnits; 77 std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; 78 std::unique_ptr<DWARFDebugMacro> MacroDWO; 79 80 /// The maximum DWARF version of all units. 81 unsigned MaxVersion = 0; 82 83 struct DWOFile { 84 object::OwningBinary<object::ObjectFile> File; 85 std::unique_ptr<DWARFContext> Context; 86 }; 87 StringMap<std::weak_ptr<DWOFile>> DWOFiles; 88 std::weak_ptr<DWOFile> DWP; 89 bool CheckedForDWP = false; 90 std::string DWPName; 91 92 std::unique_ptr<MCRegisterInfo> RegInfo; 93 94 /// Read compile units from the debug_info section (if necessary) 95 /// and type units from the debug_types sections (if necessary) 96 /// and store them in NormalUnits. 97 void parseNormalUnits(); 98 99 /// Read compile units from the debug_info.dwo section (if necessary) 100 /// and type units from the debug_types.dwo section (if necessary) 101 /// and store them in DWOUnits. 102 /// If \p Lazy is true, set up to parse but don't actually parse them. 103 enum { EagerParse = false, LazyParse = true }; 104 void parseDWOUnits(bool Lazy = false); 105 106 std::unique_ptr<const DWARFObject> DObj; 107 108 public: 109 DWARFContext(std::unique_ptr<const DWARFObject> DObj, 110 std::string DWPName = ""); 111 ~DWARFContext(); 112 113 DWARFContext(DWARFContext &) = delete; 114 DWARFContext &operator=(DWARFContext &) = delete; 115 getDWARFObj()116 const DWARFObject &getDWARFObj() const { return *DObj; } 117 classof(const DIContext * DICtx)118 static bool classof(const DIContext *DICtx) { 119 return DICtx->getKind() == CK_DWARF; 120 } 121 122 /// Dump a textual representation to \p OS. If any \p DumpOffsets are present, 123 /// dump only the record at the specified offset. 124 void dump(raw_ostream &OS, DIDumpOptions DumpOpts, 125 std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets); 126 dump(raw_ostream & OS,DIDumpOptions DumpOpts)127 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override { 128 std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets; 129 dump(OS, DumpOpts, DumpOffsets); 130 } 131 132 bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; 133 134 using unit_iterator_range = DWARFUnitVector::iterator_range; 135 136 /// Get units from .debug_info in this context. info_section_units()137 unit_iterator_range info_section_units() { 138 parseNormalUnits(); 139 return unit_iterator_range(NormalUnits.begin(), 140 NormalUnits.begin() + 141 NormalUnits.getNumInfoUnits()); 142 } 143 144 /// Get units from .debug_types in this context. types_section_units()145 unit_iterator_range types_section_units() { 146 parseNormalUnits(); 147 return unit_iterator_range( 148 NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end()); 149 } 150 151 /// Get compile units in this context. compile_units()152 unit_iterator_range compile_units() { return info_section_units(); } 153 154 /// Get type units in this context. type_units()155 unit_iterator_range type_units() { return types_section_units(); } 156 157 /// Get all normal compile/type units in this context. normal_units()158 unit_iterator_range normal_units() { 159 parseNormalUnits(); 160 return unit_iterator_range(NormalUnits.begin(), NormalUnits.end()); 161 } 162 163 /// Get units from .debug_info..dwo in the DWO context. dwo_info_section_units()164 unit_iterator_range dwo_info_section_units() { 165 parseDWOUnits(); 166 return unit_iterator_range(DWOUnits.begin(), 167 DWOUnits.begin() + DWOUnits.getNumInfoUnits()); 168 } 169 170 /// Get units from .debug_types.dwo in the DWO context. dwo_types_section_units()171 unit_iterator_range dwo_types_section_units() { 172 parseDWOUnits(); 173 return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(), 174 DWOUnits.end()); 175 } 176 177 /// Get compile units in the DWO context. dwo_compile_units()178 unit_iterator_range dwo_compile_units() { return dwo_info_section_units(); } 179 180 /// Get type units in the DWO context. dwo_type_units()181 unit_iterator_range dwo_type_units() { return dwo_types_section_units(); } 182 183 /// Get all units in the DWO context. dwo_units()184 unit_iterator_range dwo_units() { 185 parseDWOUnits(); 186 return unit_iterator_range(DWOUnits.begin(), DWOUnits.end()); 187 } 188 189 /// Get the number of compile units in this context. getNumCompileUnits()190 unsigned getNumCompileUnits() { 191 parseNormalUnits(); 192 return NormalUnits.getNumInfoUnits(); 193 } 194 195 /// Get the number of type units in this context. getNumTypeUnits()196 unsigned getNumTypeUnits() { 197 parseNormalUnits(); 198 return NormalUnits.getNumTypesUnits(); 199 } 200 201 /// Get the number of compile units in the DWO context. getNumDWOCompileUnits()202 unsigned getNumDWOCompileUnits() { 203 parseDWOUnits(); 204 return DWOUnits.getNumInfoUnits(); 205 } 206 207 /// Get the number of type units in the DWO context. getNumDWOTypeUnits()208 unsigned getNumDWOTypeUnits() { 209 parseDWOUnits(); 210 return DWOUnits.getNumTypesUnits(); 211 } 212 213 /// Get the unit at the specified index. getUnitAtIndex(unsigned index)214 DWARFUnit *getUnitAtIndex(unsigned index) { 215 parseNormalUnits(); 216 return NormalUnits[index].get(); 217 } 218 219 /// Get the unit at the specified index for the DWO units. getDWOUnitAtIndex(unsigned index)220 DWARFUnit *getDWOUnitAtIndex(unsigned index) { 221 parseDWOUnits(); 222 return DWOUnits[index].get(); 223 } 224 225 DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); 226 227 /// Return the compile unit that includes an offset (relative to .debug_info). 228 DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset); 229 230 /// Get a DIE given an exact offset. 231 DWARFDie getDIEForOffset(uint64_t Offset); 232 getMaxVersion()233 unsigned getMaxVersion() { 234 // Ensure info units have been parsed to discover MaxVersion 235 info_section_units(); 236 return MaxVersion; 237 } 238 getMaxDWOVersion()239 unsigned getMaxDWOVersion() { 240 // Ensure DWO info units have been parsed to discover MaxVersion 241 dwo_info_section_units(); 242 return MaxVersion; 243 } 244 setMaxVersionIfGreater(unsigned Version)245 void setMaxVersionIfGreater(unsigned Version) { 246 if (Version > MaxVersion) 247 MaxVersion = Version; 248 } 249 250 const DWARFUnitIndex &getCUIndex(); 251 DWARFGdbIndex &getGdbIndex(); 252 const DWARFUnitIndex &getTUIndex(); 253 254 /// Get a pointer to the parsed DebugAbbrev object. 255 const DWARFDebugAbbrev *getDebugAbbrev(); 256 257 /// Get a pointer to the parsed DebugLoc object. 258 const DWARFDebugLoc *getDebugLoc(); 259 260 /// Get a pointer to the parsed dwo abbreviations object. 261 const DWARFDebugAbbrev *getDebugAbbrevDWO(); 262 263 /// Get a pointer to the parsed DebugAranges object. 264 const DWARFDebugAranges *getDebugAranges(); 265 266 /// Get a pointer to the parsed frame information object. 267 const DWARFDebugFrame *getDebugFrame(); 268 269 /// Get a pointer to the parsed eh frame information object. 270 const DWARFDebugFrame *getEHFrame(); 271 272 /// Get a pointer to the parsed DebugMacro object. 273 const DWARFDebugMacro *getDebugMacro(); 274 275 /// Get a pointer to the parsed DebugMacroDWO object. 276 const DWARFDebugMacro *getDebugMacroDWO(); 277 278 /// Get a reference to the parsed accelerator table object. 279 const DWARFDebugNames &getDebugNames(); 280 281 /// Get a reference to the parsed accelerator table object. 282 const AppleAcceleratorTable &getAppleNames(); 283 284 /// Get a reference to the parsed accelerator table object. 285 const AppleAcceleratorTable &getAppleTypes(); 286 287 /// Get a reference to the parsed accelerator table object. 288 const AppleAcceleratorTable &getAppleNamespaces(); 289 290 /// Get a reference to the parsed accelerator table object. 291 const AppleAcceleratorTable &getAppleObjC(); 292 293 /// Get a pointer to a parsed line table corresponding to a compile unit. 294 /// Report any parsing issues as warnings on stderr. 295 const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U); 296 297 /// Get a pointer to a parsed line table corresponding to a compile unit. 298 /// Report any recoverable parsing problems using the callback. 299 Expected<const DWARFDebugLine::LineTable *> 300 getLineTableForUnit(DWARFUnit *U, 301 function_ref<void(Error)> RecoverableErrorCallback); 302 getStringExtractor()303 DataExtractor getStringExtractor() const { 304 return DataExtractor(DObj->getStrSection(), false, 0); 305 } getLineStringExtractor()306 DataExtractor getLineStringExtractor() const { 307 return DataExtractor(DObj->getLineStrSection(), false, 0); 308 } 309 310 /// Wraps the returned DIEs for a given address. 311 struct DIEsForAddress { 312 DWARFCompileUnit *CompileUnit = nullptr; 313 DWARFDie FunctionDIE; 314 DWARFDie BlockDIE; 315 explicit operator bool() const { return CompileUnit != nullptr; } 316 }; 317 318 /// Get the compilation unit, the function DIE and lexical block DIE for the 319 /// given address where applicable. 320 /// TODO: change input parameter from "uint64_t Address" 321 /// into "SectionedAddress Address" 322 DIEsForAddress getDIEsForAddress(uint64_t Address); 323 324 DILineInfo getLineInfoForAddress( 325 object::SectionedAddress Address, 326 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; 327 DILineInfoTable getLineInfoForAddressRange( 328 object::SectionedAddress Address, uint64_t Size, 329 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; 330 DIInliningInfo getInliningInfoForAddress( 331 object::SectionedAddress Address, 332 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; 333 334 std::vector<DILocal> 335 getLocalsForAddress(object::SectionedAddress Address) override; 336 isLittleEndian()337 bool isLittleEndian() const { return DObj->isLittleEndian(); } isSupportedVersion(unsigned version)338 static bool isSupportedVersion(unsigned version) { 339 return version == 2 || version == 3 || version == 4 || version == 5; 340 } 341 342 std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath); 343 getRegisterInfo()344 const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); } 345 346 /// Function used to handle default error reporting policy. Prints a error 347 /// message and returns Continue, so DWARF context ignores the error. 348 static ErrorPolicy defaultErrorHandler(Error E); 349 static std::unique_ptr<DWARFContext> 350 create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, 351 function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler, 352 std::string DWPName = ""); 353 354 static std::unique_ptr<DWARFContext> 355 create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, 356 uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost); 357 358 /// Loads register info for the architecture of the provided object file. 359 /// Improves readability of dumped DWARF expressions. Requires the caller to 360 /// have initialized the relevant target descriptions. 361 Error loadRegisterInfo(const object::ObjectFile &Obj); 362 363 /// Get address size from CUs. 364 /// TODO: refactor compile_units() to make this const. 365 uint8_t getCUAddrSize(); 366 367 /// Dump Error as warning message to stderr. 368 static void dumpWarning(Error Warning); 369 getArch()370 Triple::ArchType getArch() const { 371 return getDWARFObj().getFile()->getArch(); 372 } 373 374 private: 375 /// Return the compile unit which contains instruction with provided 376 /// address. 377 /// TODO: change input parameter from "uint64_t Address" 378 /// into "SectionedAddress Address" 379 DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); 380 void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die, 381 std::vector<DILocal> &Result); 382 }; 383 384 } // end namespace llvm 385 386 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H 387