Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- DIContext.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. // This file defines DIContext, an abstract data structure that holds
  10. // debug information data.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_DEBUGINFO_DICONTEXT_H
  15. #define LLVM_DEBUGINFO_DICONTEXT_H
  16.  
  17. #include "llvm/ADT/SmallVector.h"
  18. #include "llvm/Object/ObjectFile.h"
  19. #include "llvm/Support/WithColor.h"
  20. #include "llvm/Support/raw_ostream.h"
  21. #include <cassert>
  22. #include <cstdint>
  23. #include <memory>
  24. #include <optional>
  25. #include <string>
  26. #include <tuple>
  27. #include <utility>
  28.  
  29. namespace llvm {
  30.  
  31. /// A format-neutral container for source line information.
  32. struct DILineInfo {
  33.   // DILineInfo contains "<invalid>" for function/filename it cannot fetch.
  34.   static constexpr const char *const BadString = "<invalid>";
  35.   // Use "??" instead of "<invalid>" to make our output closer to addr2line.
  36.   static constexpr const char *const Addr2LineBadString = "??";
  37.   std::string FileName;
  38.   std::string FunctionName;
  39.   std::string StartFileName;
  40.   std::optional<StringRef> Source;
  41.   uint32_t Line = 0;
  42.   uint32_t Column = 0;
  43.   uint32_t StartLine = 0;
  44.   std::optional<uint64_t> StartAddress;
  45.  
  46.   // DWARF-specific.
  47.   uint32_t Discriminator = 0;
  48.  
  49.   DILineInfo()
  50.       : FileName(BadString), FunctionName(BadString), StartFileName(BadString) {
  51.   }
  52.  
  53.   bool operator==(const DILineInfo &RHS) const {
  54.     return Line == RHS.Line && Column == RHS.Column &&
  55.            FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
  56.            StartFileName == RHS.StartFileName && StartLine == RHS.StartLine &&
  57.            Discriminator == RHS.Discriminator;
  58.   }
  59.  
  60.   bool operator!=(const DILineInfo &RHS) const { return !(*this == RHS); }
  61.  
  62.   bool operator<(const DILineInfo &RHS) const {
  63.     return std::tie(FileName, FunctionName, StartFileName, Line, Column,
  64.                     StartLine, Discriminator) <
  65.            std::tie(RHS.FileName, RHS.FunctionName, RHS.StartFileName, RHS.Line,
  66.                     RHS.Column, RHS.StartLine, RHS.Discriminator);
  67.   }
  68.  
  69.   explicit operator bool() const { return *this != DILineInfo(); }
  70.  
  71.   void dump(raw_ostream &OS) {
  72.     OS << "Line info: ";
  73.     if (FileName != BadString)
  74.       OS << "file '" << FileName << "', ";
  75.     if (FunctionName != BadString)
  76.       OS << "function '" << FunctionName << "', ";
  77.     OS << "line " << Line << ", ";
  78.     OS << "column " << Column << ", ";
  79.     if (StartFileName != BadString)
  80.       OS << "start file '" << StartFileName << "', ";
  81.     OS << "start line " << StartLine << '\n';
  82.   }
  83. };
  84.  
  85. using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>;
  86.  
  87. /// A format-neutral container for inlined code description.
  88. class DIInliningInfo {
  89.   SmallVector<DILineInfo, 4> Frames;
  90.  
  91. public:
  92.   DIInliningInfo() = default;
  93.  
  94.   /// Returns the frame at `Index`. Frames are stored in bottom-up
  95.   /// (leaf-to-root) order with increasing index.
  96.   const DILineInfo &getFrame(unsigned Index) const {
  97.     assert(Index < Frames.size());
  98.     return Frames[Index];
  99.   }
  100.  
  101.   DILineInfo *getMutableFrame(unsigned Index) {
  102.     assert(Index < Frames.size());
  103.     return &Frames[Index];
  104.   }
  105.  
  106.   uint32_t getNumberOfFrames() const { return Frames.size(); }
  107.  
  108.   void addFrame(const DILineInfo &Frame) { Frames.push_back(Frame); }
  109.  
  110.   void resize(unsigned i) { Frames.resize(i); }
  111. };
  112.  
  113. /// Container for description of a global variable.
  114. struct DIGlobal {
  115.   std::string Name;
  116.   uint64_t Start = 0;
  117.   uint64_t Size = 0;
  118.   std::string DeclFile;
  119.   uint64_t DeclLine = 0;
  120.  
  121.   DIGlobal() : Name(DILineInfo::BadString) {}
  122. };
  123.  
  124. struct DILocal {
  125.   std::string FunctionName;
  126.   std::string Name;
  127.   std::string DeclFile;
  128.   uint64_t DeclLine = 0;
  129.   std::optional<int64_t> FrameOffset;
  130.   std::optional<uint64_t> Size;
  131.   std::optional<uint64_t> TagOffset;
  132. };
  133.  
  134. /// A DINameKind is passed to name search methods to specify a
  135. /// preference regarding the type of name resolution the caller wants.
  136. enum class DINameKind { None, ShortName, LinkageName };
  137.  
  138. /// Controls which fields of DILineInfo container should be filled
  139. /// with data.
  140. struct DILineInfoSpecifier {
  141.   enum class FileLineInfoKind {
  142.     None,
  143.     // RawValue is whatever the compiler stored in the filename table.  Could be
  144.     // a full path, could be something else.
  145.     RawValue,
  146.     BaseNameOnly,
  147.     // Relative to the compilation directory.
  148.     RelativeFilePath,
  149.     AbsoluteFilePath
  150.   };
  151.   using FunctionNameKind = DINameKind;
  152.  
  153.   FileLineInfoKind FLIKind;
  154.   FunctionNameKind FNKind;
  155.  
  156.   DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::RawValue,
  157.                       FunctionNameKind FNKind = FunctionNameKind::None)
  158.       : FLIKind(FLIKind), FNKind(FNKind) {}
  159.  
  160.   inline bool operator==(const DILineInfoSpecifier &RHS) const {
  161.     return FLIKind == RHS.FLIKind && FNKind == RHS.FNKind;
  162.   }
  163. };
  164.  
  165. /// This is just a helper to programmatically construct DIDumpType.
  166. enum DIDumpTypeCounter {
  167. #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
  168.   DIDT_ID_##ENUM_NAME,
  169. #include "llvm/BinaryFormat/Dwarf.def"
  170. #undef HANDLE_DWARF_SECTION
  171.   DIDT_ID_UUID,
  172.   DIDT_ID_Count
  173. };
  174. static_assert(DIDT_ID_Count <= 32, "section types overflow storage");
  175.  
  176. /// Selects which debug sections get dumped.
  177. enum DIDumpType : unsigned {
  178.   DIDT_Null,
  179.   DIDT_All = ~0U,
  180. #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
  181.   DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
  182. #include "llvm/BinaryFormat/Dwarf.def"
  183. #undef HANDLE_DWARF_SECTION
  184.   DIDT_UUID = 1 << DIDT_ID_UUID,
  185. };
  186.  
  187. /// Container for dump options that control which debug information will be
  188. /// dumped.
  189. struct DIDumpOptions {
  190.   unsigned DumpType = DIDT_All;
  191.   unsigned ChildRecurseDepth = -1U;
  192.   unsigned ParentRecurseDepth = -1U;
  193.   uint16_t Version = 0; // DWARF version to assume when extracting.
  194.   uint8_t AddrSize = 4; // Address byte size to assume when extracting.
  195.   bool ShowAddresses = true;
  196.   bool ShowChildren = false;
  197.   bool ShowParents = false;
  198.   bool ShowForm = false;
  199.   bool SummarizeTypes = false;
  200.   bool Verbose = false;
  201.   bool DisplayRawContents = false;
  202.   bool IsEH = false;
  203.   std::function<llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)>
  204.       GetNameForDWARFReg;
  205.  
  206.   /// Return default option set for printing a single DIE without children.
  207.   static DIDumpOptions getForSingleDIE() {
  208.     DIDumpOptions Opts;
  209.     Opts.ChildRecurseDepth = 0;
  210.     Opts.ParentRecurseDepth = 0;
  211.     return Opts;
  212.   }
  213.  
  214.   /// Return the options with RecurseDepth set to 0 unless explicitly required.
  215.   DIDumpOptions noImplicitRecursion() const {
  216.     DIDumpOptions Opts = *this;
  217.     if (ChildRecurseDepth == -1U && !ShowChildren)
  218.       Opts.ChildRecurseDepth = 0;
  219.     if (ParentRecurseDepth == -1U && !ShowParents)
  220.       Opts.ParentRecurseDepth = 0;
  221.     return Opts;
  222.   }
  223.  
  224.   std::function<void(Error)> RecoverableErrorHandler =
  225.       WithColor::defaultErrorHandler;
  226.   std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
  227. };
  228.  
  229. class DIContext {
  230. public:
  231.   enum DIContextKind { CK_DWARF, CK_PDB };
  232.  
  233.   DIContext(DIContextKind K) : Kind(K) {}
  234.   virtual ~DIContext() = default;
  235.  
  236.   DIContextKind getKind() const { return Kind; }
  237.  
  238.   virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
  239.  
  240.   virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) {
  241.     // No verifier? Just say things went well.
  242.     return true;
  243.   }
  244.  
  245.   virtual DILineInfo getLineInfoForAddress(
  246.       object::SectionedAddress Address,
  247.       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
  248.   virtual DILineInfo
  249.   getLineInfoForDataAddress(object::SectionedAddress Address) = 0;
  250.   virtual DILineInfoTable getLineInfoForAddressRange(
  251.       object::SectionedAddress Address, uint64_t Size,
  252.       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
  253.   virtual DIInliningInfo getInliningInfoForAddress(
  254.       object::SectionedAddress Address,
  255.       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
  256.  
  257.   virtual std::vector<DILocal>
  258.   getLocalsForAddress(object::SectionedAddress Address) = 0;
  259.  
  260. private:
  261.   const DIContextKind Kind;
  262. };
  263.  
  264. /// An inferface for inquiring the load address of a loaded object file
  265. /// to be used by the DIContext implementations when applying relocations
  266. /// on the fly.
  267. class LoadedObjectInfo {
  268. protected:
  269.   LoadedObjectInfo() = default;
  270.   LoadedObjectInfo(const LoadedObjectInfo &) = default;
  271.  
  272. public:
  273.   virtual ~LoadedObjectInfo() = default;
  274.  
  275.   /// Obtain the Load Address of a section by SectionRef.
  276.   ///
  277.   /// Calculate the address of the given section.
  278.   /// The section need not be present in the local address space. The addresses
  279.   /// need to be consistent with the addresses used to query the DIContext and
  280.   /// the output of this function should be deterministic, i.e. repeated calls
  281.   /// with the same Sec should give the same address.
  282.   virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const {
  283.     return 0;
  284.   }
  285.  
  286.   /// If conveniently available, return the content of the given Section.
  287.   ///
  288.   /// When the section is available in the local address space, in relocated
  289.   /// (loaded) form, e.g. because it was relocated by a JIT for execution, this
  290.   /// function should provide the contents of said section in `Data`. If the
  291.   /// loaded section is not available, or the cost of retrieving it would be
  292.   /// prohibitive, this function should return false. In that case, relocations
  293.   /// will be read from the local (unrelocated) object file and applied on the
  294.   /// fly. Note that this method is used purely for optimzation purposes in the
  295.   /// common case of JITting in the local address space, so returning false
  296.   /// should always be correct.
  297.   virtual bool getLoadedSectionContents(const object::SectionRef &Sec,
  298.                                         StringRef &Data) const {
  299.     return false;
  300.   }
  301.  
  302.   // FIXME: This is untested and unused anywhere in the LLVM project, it's
  303.   // used/needed by Julia (an external project). It should have some coverage
  304.   // (at least tests, but ideally example functionality).
  305.   /// Obtain a copy of this LoadedObjectInfo.
  306.   virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0;
  307. };
  308.  
  309. template <typename Derived, typename Base = LoadedObjectInfo>
  310. struct LoadedObjectInfoHelper : Base {
  311. protected:
  312.   LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default;
  313.   LoadedObjectInfoHelper() = default;
  314.  
  315. public:
  316.   template <typename... Ts>
  317.   LoadedObjectInfoHelper(Ts &&...Args) : Base(std::forward<Ts>(Args)...) {}
  318.  
  319.   std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
  320.     return std::make_unique<Derived>(static_cast<const Derived &>(*this));
  321.   }
  322. };
  323.  
  324. } // end namespace llvm
  325.  
  326. #endif // LLVM_DEBUGINFO_DICONTEXT_H
  327.