diff options
Diffstat (limited to 'third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFContext.h')
-rw-r--r-- | third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFContext.h | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFContext.h b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFContext.h new file mode 100644 index 000000000..2dec107d1 --- /dev/null +++ b/third_party/llvm-project/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -0,0 +1,382 @@ +//===- DWARFContext.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===/ + +#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/DataExtractor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Host.h" +#include <cstdint> +#include <deque> +#include <map> +#include <memory> + +namespace llvm { + +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 { + DWARFUnitVector NormalUnits; + 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<DWARFDebugNames> Names; + std::unique_ptr<AppleAcceleratorTable> AppleNames; + std::unique_ptr<AppleAcceleratorTable> AppleTypes; + std::unique_ptr<AppleAcceleratorTable> AppleNamespaces; + std::unique_ptr<AppleAcceleratorTable> AppleObjC; + + DWARFUnitVector DWOUnits; + std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; + + /// 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 type units from the debug_types sections (if necessary) + /// and store them in NormalUnits. + void parseNormalUnits(); + + /// Read compile units from the debug_info.dwo section (if necessary) + /// and type units from the debug_types.dwo section (if necessary) + /// and store them in DWOUnits. + /// If \p Lazy is true, set up to parse but don't actually parse them. + enum { EagerParse = false, LazyParse = true }; + void parseDWOUnits(bool Lazy = false); + + 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 unit_iterator_range = DWARFUnitVector::iterator_range; + + /// Get units from .debug_info in this context. + unit_iterator_range info_section_units() { + parseNormalUnits(); + return unit_iterator_range(NormalUnits.begin(), + NormalUnits.begin() + + NormalUnits.getNumInfoUnits()); + } + + /// Get units from .debug_types in this context. + unit_iterator_range types_section_units() { + parseNormalUnits(); + return unit_iterator_range( + NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end()); + } + + /// Get compile units in this context. + unit_iterator_range compile_units() { return info_section_units(); } + + /// Get type units in this context. + unit_iterator_range type_units() { return types_section_units(); } + + /// Get all normal compile/type units in this context. + unit_iterator_range normal_units() { + parseNormalUnits(); + return unit_iterator_range(NormalUnits.begin(), NormalUnits.end()); + } + + /// Get units from .debug_info..dwo in the DWO context. + unit_iterator_range dwo_info_section_units() { + parseDWOUnits(); + return unit_iterator_range(DWOUnits.begin(), + DWOUnits.begin() + DWOUnits.getNumInfoUnits()); + } + + /// Get units from .debug_types.dwo in the DWO context. + unit_iterator_range dwo_types_section_units() { + parseDWOUnits(); + return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(), + DWOUnits.end()); + } + + /// Get compile units in the DWO context. + unit_iterator_range dwo_compile_units() { return dwo_info_section_units(); } + + /// Get type units in the DWO context. + unit_iterator_range dwo_type_units() { return dwo_types_section_units(); } + + /// Get all units in the DWO context. + unit_iterator_range dwo_units() { + parseDWOUnits(); + return unit_iterator_range(DWOUnits.begin(), DWOUnits.end()); + } + + /// Get the number of compile units in this context. + unsigned getNumCompileUnits() { + parseNormalUnits(); + return NormalUnits.getNumInfoUnits(); + } + + /// Get the number of type units in this context. + unsigned getNumTypeUnits() { + parseNormalUnits(); + return NormalUnits.getNumTypesUnits(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOCompileUnits() { + parseDWOUnits(); + return DWOUnits.getNumInfoUnits(); + } + + /// Get the number of type units in the DWO context. + unsigned getNumDWOTypeUnits() { + parseDWOUnits(); + return DWOUnits.getNumTypesUnits(); + } + + /// Get the unit at the specified index. + DWARFUnit *getUnitAtIndex(unsigned index) { + parseNormalUnits(); + return NormalUnits[index].get(); + } + + /// Get the unit at the specified index for the DWO units. + DWARFUnit *getDWOUnitAtIndex(unsigned index) { + parseDWOUnits(); + return DWOUnits[index].get(); + } + + DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); + + /// Return the compile unit that includes an offset (relative to .debug_info). + DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset); + + /// Get a DIE given an exact offset. + DWARFDie getDIEForOffset(uint64_t Offset); + + unsigned getMaxVersion() { + // Ensure info units have been parsed to discover MaxVersion + info_section_units(); + return MaxVersion; + } + + unsigned getMaxDWOVersion() { + // Ensure DWO info units have been parsed to discover MaxVersion + dwo_info_section_units(); + 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 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 DWARFDebugNames &getDebugNames(); + + /// Get a reference to the parsed accelerator table object. + const AppleAcceleratorTable &getAppleNames(); + + /// Get a reference to the parsed accelerator table object. + const AppleAcceleratorTable &getAppleTypes(); + + /// Get a reference to the parsed accelerator table object. + const AppleAcceleratorTable &getAppleNamespaces(); + + /// Get a reference to the parsed accelerator table object. + const AppleAcceleratorTable &getAppleObjC(); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + /// Report any parsing issues as warnings on stderr. + const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + /// Report any recoverable parsing problems using the callback. + Expected<const DWARFDebugLine::LineTable *> + getLineTableForUnit(DWARFUnit *U, + std::function<void(Error)> RecoverableErrorCallback); + + DataExtractor getStringExtractor() const { + return DataExtractor(DObj->getStrSection(), false, 0); + } + DataExtractor getLineStringExtractor() const { + return DataExtractor(DObj->getLineStrSection(), false, 0); + } + + /// Wraps the returned DIEs for a given address. + struct DIEsForAddress { + DWARFCompileUnit *CompileUnit = nullptr; + DWARFDie FunctionDIE; + DWARFDie BlockDIE; + explicit operator bool() const { return CompileUnit != nullptr; } + }; + + /// Get the compilation unit, the function DIE and lexical block DIE for the + /// given address where applicable. + /// TODO: change input parameter from "uint64_t Address" + /// into "SectionedAddress Address" + DIEsForAddress getDIEsForAddress(uint64_t Address); + + DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + + std::vector<DILocal> + getLocalsForAddress(object::SectionedAddress Address) 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); + + /// Get address size from CUs. + /// TODO: refactor compile_units() to make this const. + uint8_t getCUAddrSize(); + + /// Dump Error as warning message to stderr. + static void dumpWarning(Error Warning); + + Triple::ArchType getArch() const { + return getDWARFObj().getFile()->getArch(); + } + +private: + /// Return the compile unit which contains instruction with provided + /// address. + /// TODO: change input parameter from "uint64_t Address" + /// into "SectionedAddress Address" + DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); + void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die, + std::vector<DILocal> &Result); +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H |