| //===- DWARFContext.h -------------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===/ |
| |
| #ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H |
| #define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H |
| |
| #include "llvm/ADT/MapVector.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/iterator_range.h" |
| #include "llvm/DebugInfo/DIContext.h" |
| #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" |
| #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" |
| #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" |
| #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" |
| #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" |
| #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" |
| #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" |
| #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" |
| #include "llvm/DebugInfo/DWARF/DWARFDie.h" |
| #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" |
| #include "llvm/DebugInfo/DWARF/DWARFObject.h" |
| #include "llvm/DebugInfo/DWARF/DWARFSection.h" |
| #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" |
| #include "llvm/DebugInfo/DWARF/DWARFUnit.h" |
| #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" |
| #include "llvm/Object/Binary.h" |
| #include "llvm/Object/ObjectFile.h" |
| #include "llvm/Support/Error.h" |
| #include "llvm/Support/Host.h" |
| #include <cstdint> |
| #include <deque> |
| #include <map> |
| #include <memory> |
| |
| namespace llvm { |
| |
| class DataExtractor; |
| class MCRegisterInfo; |
| class MemoryBuffer; |
| class raw_ostream; |
| |
| /// Used as a return value for a error callback passed to DWARF context. |
| /// Callback should return Halt if client application wants to stop |
| /// object parsing, or should return Continue otherwise. |
| enum class ErrorPolicy { Halt, Continue }; |
| |
| /// DWARFContext |
| /// This data structure is the top level entity that deals with dwarf debug |
| /// information parsing. The actual data is supplied through DWARFObj. |
| class DWARFContext : public DIContext { |
| DWARFUnitSection<DWARFCompileUnit> CUs; |
| std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs; |
| std::unique_ptr<DWARFUnitIndex> CUIndex; |
| std::unique_ptr<DWARFGdbIndex> GdbIndex; |
| std::unique_ptr<DWARFUnitIndex> TUIndex; |
| std::unique_ptr<DWARFDebugAbbrev> Abbrev; |
| std::unique_ptr<DWARFDebugLoc> Loc; |
| std::unique_ptr<DWARFDebugAranges> Aranges; |
| std::unique_ptr<DWARFDebugLine> Line; |
| std::unique_ptr<DWARFDebugFrame> DebugFrame; |
| std::unique_ptr<DWARFDebugFrame> EHFrame; |
| std::unique_ptr<DWARFDebugMacro> Macro; |
| std::unique_ptr<DWARFAcceleratorTable> AppleNames; |
| std::unique_ptr<DWARFAcceleratorTable> AppleTypes; |
| std::unique_ptr<DWARFAcceleratorTable> AppleNamespaces; |
| std::unique_ptr<DWARFAcceleratorTable> AppleObjC; |
| |
| DWARFUnitSection<DWARFCompileUnit> DWOCUs; |
| std::deque<DWARFUnitSection<DWARFTypeUnit>> DWOTUs; |
| std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; |
| std::unique_ptr<DWARFDebugLocDWO> LocDWO; |
| |
| /// The maximum DWARF version of all units. |
| unsigned MaxVersion = 0; |
| |
| struct DWOFile { |
| object::OwningBinary<object::ObjectFile> File; |
| std::unique_ptr<DWARFContext> Context; |
| }; |
| StringMap<std::weak_ptr<DWOFile>> DWOFiles; |
| std::weak_ptr<DWOFile> DWP; |
| bool CheckedForDWP = false; |
| std::string DWPName; |
| |
| std::unique_ptr<MCRegisterInfo> RegInfo; |
| |
| /// Read compile units from the debug_info section (if necessary) |
| /// and store them in CUs. |
| void parseCompileUnits(); |
| |
| /// Read type units from the debug_types sections (if necessary) |
| /// and store them in TUs. |
| void parseTypeUnits(); |
| |
| /// Read compile units from the debug_info.dwo section (if necessary) |
| /// and store them in DWOCUs. |
| void parseDWOCompileUnits(); |
| |
| /// Read type units from the debug_types.dwo section (if necessary) |
| /// and store them in DWOTUs. |
| void parseDWOTypeUnits(); |
| |
| protected: |
| std::unique_ptr<const DWARFObject> DObj; |
| |
| public: |
| DWARFContext(std::unique_ptr<const DWARFObject> DObj, |
| std::string DWPName = ""); |
| ~DWARFContext(); |
| |
| DWARFContext(DWARFContext &) = delete; |
| DWARFContext &operator=(DWARFContext &) = delete; |
| |
| const DWARFObject &getDWARFObj() const { return *DObj; } |
| |
| static bool classof(const DIContext *DICtx) { |
| return DICtx->getKind() == CK_DWARF; |
| } |
| |
| /// Dump a textual representation to \p OS. If any \p DumpOffsets are present, |
| /// dump only the record at the specified offset. |
| void dump(raw_ostream &OS, DIDumpOptions DumpOpts, |
| std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets); |
| |
| void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override { |
| std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets; |
| dump(OS, DumpOpts, DumpOffsets); |
| } |
| |
| bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; |
| |
| using cu_iterator_range = DWARFUnitSection<DWARFCompileUnit>::iterator_range; |
| using tu_iterator_range = DWARFUnitSection<DWARFTypeUnit>::iterator_range; |
| using tu_section_iterator_range = iterator_range<decltype(TUs)::iterator>; |
| |
| /// Get compile units in this context. |
| cu_iterator_range compile_units() { |
| parseCompileUnits(); |
| return cu_iterator_range(CUs.begin(), CUs.end()); |
| } |
| |
| /// Get type units in this context. |
| tu_section_iterator_range type_unit_sections() { |
| parseTypeUnits(); |
| return tu_section_iterator_range(TUs.begin(), TUs.end()); |
| } |
| |
| /// Get compile units in the DWO context. |
| cu_iterator_range dwo_compile_units() { |
| parseDWOCompileUnits(); |
| return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); |
| } |
| |
| /// Get type units in the DWO context. |
| tu_section_iterator_range dwo_type_unit_sections() { |
| parseDWOTypeUnits(); |
| return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end()); |
| } |
| |
| /// Get the number of compile units in this context. |
| unsigned getNumCompileUnits() { |
| parseCompileUnits(); |
| return CUs.size(); |
| } |
| |
| /// Get the number of compile units in this context. |
| unsigned getNumTypeUnits() { |
| parseTypeUnits(); |
| return TUs.size(); |
| } |
| |
| /// Get the number of compile units in the DWO context. |
| unsigned getNumDWOCompileUnits() { |
| parseDWOCompileUnits(); |
| return DWOCUs.size(); |
| } |
| |
| /// Get the number of compile units in the DWO context. |
| unsigned getNumDWOTypeUnits() { |
| parseDWOTypeUnits(); |
| return DWOTUs.size(); |
| } |
| |
| /// Get the compile unit at the specified index for this compile unit. |
| DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { |
| parseCompileUnits(); |
| return CUs[index].get(); |
| } |
| |
| /// Get the compile unit at the specified index for the DWO compile units. |
| DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { |
| parseDWOCompileUnits(); |
| return DWOCUs[index].get(); |
| } |
| |
| DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); |
| |
| /// Get a DIE given an exact offset. |
| DWARFDie getDIEForOffset(uint32_t Offset); |
| |
| unsigned getMaxVersion() const { return MaxVersion; } |
| |
| void setMaxVersionIfGreater(unsigned Version) { |
| if (Version > MaxVersion) |
| MaxVersion = Version; |
| } |
| |
| const DWARFUnitIndex &getCUIndex(); |
| DWARFGdbIndex &getGdbIndex(); |
| const DWARFUnitIndex &getTUIndex(); |
| |
| /// Get a pointer to the parsed DebugAbbrev object. |
| const DWARFDebugAbbrev *getDebugAbbrev(); |
| |
| /// Get a pointer to the parsed DebugLoc object. |
| const DWARFDebugLoc *getDebugLoc(); |
| |
| /// Get a pointer to the parsed dwo abbreviations object. |
| const DWARFDebugAbbrev *getDebugAbbrevDWO(); |
| |
| /// Get a pointer to the parsed DebugLoc object. |
| const DWARFDebugLocDWO *getDebugLocDWO(); |
| |
| /// Get a pointer to the parsed DebugAranges object. |
| const DWARFDebugAranges *getDebugAranges(); |
| |
| /// Get a pointer to the parsed frame information object. |
| const DWARFDebugFrame *getDebugFrame(); |
| |
| /// Get a pointer to the parsed eh frame information object. |
| const DWARFDebugFrame *getEHFrame(); |
| |
| /// Get a pointer to the parsed DebugMacro object. |
| const DWARFDebugMacro *getDebugMacro(); |
| |
| /// Get a reference to the parsed accelerator table object. |
| const DWARFAcceleratorTable &getAppleNames(); |
| |
| /// Get a reference to the parsed accelerator table object. |
| const DWARFAcceleratorTable &getAppleTypes(); |
| |
| /// Get a reference to the parsed accelerator table object. |
| const DWARFAcceleratorTable &getAppleNamespaces(); |
| |
| /// Get a reference to the parsed accelerator table object. |
| const DWARFAcceleratorTable &getAppleObjC(); |
| |
| /// Get a pointer to a parsed line table corresponding to a compile unit. |
| const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu); |
| |
| DILineInfo getLineInfoForAddress(uint64_t Address, |
| DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; |
| DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, |
| DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; |
| DIInliningInfo getInliningInfoForAddress(uint64_t Address, |
| DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; |
| |
| bool isLittleEndian() const { return DObj->isLittleEndian(); } |
| static bool isSupportedVersion(unsigned version) { |
| return version == 2 || version == 3 || version == 4 || version == 5; |
| } |
| |
| std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath); |
| |
| const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); } |
| |
| /// Function used to handle default error reporting policy. Prints a error |
| /// message and returns Continue, so DWARF context ignores the error. |
| static ErrorPolicy defaultErrorHandler(Error E); |
| static std::unique_ptr<DWARFContext> |
| create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, |
| function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler, |
| std::string DWPName = ""); |
| |
| static std::unique_ptr<DWARFContext> |
| create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, |
| uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost); |
| |
| /// Loads register info for the architecture of the provided object file. |
| /// Improves readability of dumped DWARF expressions. Requires the caller to |
| /// have initialized the relevant target descriptions. |
| Error loadRegisterInfo(const object::ObjectFile &Obj); |
| |
| private: |
| /// Return the compile unit that includes an offset (relative to .debug_info). |
| DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); |
| |
| /// Return the compile unit which contains instruction with provided |
| /// address. |
| DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); |
| }; |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H |