diff options
Diffstat (limited to 'third_party/llvm-project/include/llvm/DebugInfo/DIContext.h')
-rw-r--r-- | third_party/llvm-project/include/llvm/DebugInfo/DIContext.h | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/third_party/llvm-project/include/llvm/DebugInfo/DIContext.h b/third_party/llvm-project/include/llvm/DebugInfo/DIContext.h new file mode 100644 index 000000000..fbebfe634 --- /dev/null +++ b/third_party/llvm-project/include/llvm/DebugInfo/DIContext.h @@ -0,0 +1,302 @@ +//===- DIContext.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 +// +//===----------------------------------------------------------------------===// +// +// This file defines DIContext, an abstract data structure that holds +// debug information data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DICONTEXT_H +#define LLVM_DEBUGINFO_DICONTEXT_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <string> +#include <tuple> +#include <utility> + +namespace llvm { + +/// A format-neutral container for source line information. +struct DILineInfo { + // DILineInfo contains "<invalid>" for function/filename it cannot fetch. + static constexpr const char *const BadString = "<invalid>"; + // Use "??" instead of "<invalid>" to make our output closer to addr2line. + static constexpr const char *const Addr2LineBadString = "??"; + std::string FileName; + std::string FunctionName; + Optional<StringRef> Source; + uint32_t Line = 0; + uint32_t Column = 0; + uint32_t StartLine = 0; + + // DWARF-specific. + uint32_t Discriminator = 0; + + DILineInfo() : FileName(BadString), FunctionName(BadString) {} + + bool operator==(const DILineInfo &RHS) const { + return Line == RHS.Line && Column == RHS.Column && + FileName == RHS.FileName && FunctionName == RHS.FunctionName && + StartLine == RHS.StartLine && Discriminator == RHS.Discriminator; + } + + bool operator!=(const DILineInfo &RHS) const { + return !(*this == RHS); + } + + bool operator<(const DILineInfo &RHS) const { + return std::tie(FileName, FunctionName, Line, Column, StartLine, + Discriminator) < + std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column, + RHS.StartLine, RHS.Discriminator); + } + + explicit operator bool() const { return *this != DILineInfo(); } + + void dump(raw_ostream &OS) { + OS << "Line info: "; + if (FileName != BadString) + OS << "file '" << FileName << "', "; + if (FunctionName != BadString) + OS << "function '" << FunctionName << "', "; + OS << "line " << Line << ", "; + OS << "column " << Column << ", "; + OS << "start line " << StartLine << '\n'; + } +}; + +using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>; + +/// A format-neutral container for inlined code description. +class DIInliningInfo { + SmallVector<DILineInfo, 4> Frames; + +public: + DIInliningInfo() = default; + + const DILineInfo & getFrame(unsigned Index) const { + assert(Index < Frames.size()); + return Frames[Index]; + } + + DILineInfo *getMutableFrame(unsigned Index) { + assert(Index < Frames.size()); + return &Frames[Index]; + } + + uint32_t getNumberOfFrames() const { + return Frames.size(); + } + + void addFrame(const DILineInfo &Frame) { + Frames.push_back(Frame); + } + + void resize(unsigned i) { + Frames.resize(i); + } +}; + +/// Container for description of a global variable. +struct DIGlobal { + std::string Name; + uint64_t Start = 0; + uint64_t Size = 0; + + DIGlobal() : Name(DILineInfo::BadString) {} +}; + +struct DILocal { + std::string FunctionName; + std::string Name; + std::string DeclFile; + uint64_t DeclLine = 0; + Optional<int64_t> FrameOffset; + Optional<uint64_t> Size; + Optional<uint64_t> TagOffset; +}; + +/// A DINameKind is passed to name search methods to specify a +/// preference regarding the type of name resolution the caller wants. +enum class DINameKind { None, ShortName, LinkageName }; + +/// Controls which fields of DILineInfo container should be filled +/// with data. +struct DILineInfoSpecifier { + enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; + using FunctionNameKind = DINameKind; + + FileLineInfoKind FLIKind; + FunctionNameKind FNKind; + + DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default, + FunctionNameKind FNKind = FunctionNameKind::None) + : FLIKind(FLIKind), FNKind(FNKind) {} +}; + +/// This is just a helper to programmatically construct DIDumpType. +enum DIDumpTypeCounter { +#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \ + DIDT_ID_##ENUM_NAME, +#include "llvm/BinaryFormat/Dwarf.def" +#undef HANDLE_DWARF_SECTION + DIDT_ID_UUID, + DIDT_ID_Count +}; +static_assert(DIDT_ID_Count <= 32, "section types overflow storage"); + +/// Selects which debug sections get dumped. +enum DIDumpType : unsigned { + DIDT_Null, + DIDT_All = ~0U, +#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \ + DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME, +#include "llvm/BinaryFormat/Dwarf.def" +#undef HANDLE_DWARF_SECTION + DIDT_UUID = 1 << DIDT_ID_UUID, +}; + +/// Container for dump options that control which debug information will be +/// dumped. +struct DIDumpOptions { + unsigned DumpType = DIDT_All; + unsigned ChildRecurseDepth = -1U; + unsigned ParentRecurseDepth = -1U; + uint16_t Version = 0; // DWARF version to assume when extracting. + uint8_t AddrSize = 4; // Address byte size to assume when extracting. + bool ShowAddresses = true; + bool ShowChildren = false; + bool ShowParents = false; + bool ShowForm = false; + bool SummarizeTypes = false; + bool Verbose = false; + bool DisplayRawContents = false; + + /// Return default option set for printing a single DIE without children. + static DIDumpOptions getForSingleDIE() { + DIDumpOptions Opts; + Opts.ChildRecurseDepth = 0; + Opts.ParentRecurseDepth = 0; + return Opts; + } + + /// Return the options with RecurseDepth set to 0 unless explicitly required. + DIDumpOptions noImplicitRecursion() const { + DIDumpOptions Opts = *this; + if (ChildRecurseDepth == -1U && !ShowChildren) + Opts.ChildRecurseDepth = 0; + if (ParentRecurseDepth == -1U && !ShowParents) + Opts.ParentRecurseDepth = 0; + return Opts; + } +}; + +class DIContext { +public: + enum DIContextKind { + CK_DWARF, + CK_PDB + }; + + DIContext(DIContextKind K) : Kind(K) {} + virtual ~DIContext() = default; + + DIContextKind getKind() const { return Kind; } + + virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0; + + virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) { + // No verifier? Just say things went well. + return true; + } + + virtual DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DIInliningInfo getInliningInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + + virtual std::vector<DILocal> + getLocalsForAddress(object::SectionedAddress Address) = 0; + +private: + const DIContextKind Kind; +}; + +/// An inferface for inquiring the load address of a loaded object file +/// to be used by the DIContext implementations when applying relocations +/// on the fly. +class LoadedObjectInfo { +protected: + LoadedObjectInfo() = default; + LoadedObjectInfo(const LoadedObjectInfo &) = default; + +public: + virtual ~LoadedObjectInfo() = default; + + /// Obtain the Load Address of a section by SectionRef. + /// + /// Calculate the address of the given section. + /// The section need not be present in the local address space. The addresses + /// need to be consistent with the addresses used to query the DIContext and + /// the output of this function should be deterministic, i.e. repeated calls + /// with the same Sec should give the same address. + virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const { + return 0; + } + + /// If conveniently available, return the content of the given Section. + /// + /// When the section is available in the local address space, in relocated + /// (loaded) form, e.g. because it was relocated by a JIT for execution, this + /// function should provide the contents of said section in `Data`. If the + /// loaded section is not available, or the cost of retrieving it would be + /// prohibitive, this function should return false. In that case, relocations + /// will be read from the local (unrelocated) object file and applied on the + /// fly. Note that this method is used purely for optimzation purposes in the + /// common case of JITting in the local address space, so returning false + /// should always be correct. + virtual bool getLoadedSectionContents(const object::SectionRef &Sec, + StringRef &Data) const { + return false; + } + + // FIXME: This is untested and unused anywhere in the LLVM project, it's + // used/needed by Julia (an external project). It should have some coverage + // (at least tests, but ideally example functionality). + /// Obtain a copy of this LoadedObjectInfo. + virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0; +}; + +template <typename Derived, typename Base = LoadedObjectInfo> +struct LoadedObjectInfoHelper : Base { +protected: + LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default; + LoadedObjectInfoHelper() = default; + +public: + template <typename... Ts> + LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {} + + std::unique_ptr<llvm::LoadedObjectInfo> clone() const override { + return std::make_unique<Derived>(static_cast<const Derived &>(*this)); + } +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DICONTEXT_H |