Home | History | Annotate | Download | only in DebugInfo
      1 //===- DIContext.h ----------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines DIContext, an abstract data structure that holds
     11 // debug information data.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_DEBUGINFO_DICONTEXT_H
     16 #define LLVM_DEBUGINFO_DICONTEXT_H
     17 
     18 #include "llvm/ADT/SmallVector.h"
     19 #include "llvm/Object/ObjectFile.h"
     20 #include <cassert>
     21 #include <cstdint>
     22 #include <memory>
     23 #include <string>
     24 #include <tuple>
     25 #include <utility>
     26 
     27 namespace llvm {
     28 
     29 class raw_ostream;
     30 
     31 /// A format-neutral container for source line information.
     32 struct DILineInfo {
     33   std::string FileName;
     34   std::string FunctionName;
     35   uint32_t Line = 0;
     36   uint32_t Column = 0;
     37   uint32_t StartLine = 0;
     38 
     39   // DWARF-specific.
     40   uint32_t Discriminator = 0;
     41 
     42   DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>") {}
     43 
     44   bool operator==(const DILineInfo &RHS) const {
     45     return Line == RHS.Line && Column == RHS.Column &&
     46            FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
     47            StartLine == RHS.StartLine && Discriminator == RHS.Discriminator;
     48   }
     49   bool operator!=(const DILineInfo &RHS) const {
     50     return !(*this == RHS);
     51   }
     52   bool operator<(const DILineInfo &RHS) const {
     53     return std::tie(FileName, FunctionName, Line, Column, StartLine,
     54                     Discriminator) <
     55            std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column,
     56                     RHS.StartLine, RHS.Discriminator);
     57   }
     58 };
     59 
     60 using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>;
     61 
     62 /// A format-neutral container for inlined code description.
     63 class DIInliningInfo {
     64   SmallVector<DILineInfo, 4> Frames;
     65 
     66 public:
     67   DIInliningInfo() = default;
     68 
     69   DILineInfo getFrame(unsigned Index) const {
     70     assert(Index < Frames.size());
     71     return Frames[Index];
     72   }
     73 
     74   DILineInfo *getMutableFrame(unsigned Index) {
     75     assert(Index < Frames.size());
     76     return &Frames[Index];
     77   }
     78 
     79   uint32_t getNumberOfFrames() const {
     80     return Frames.size();
     81   }
     82 
     83   void addFrame(const DILineInfo &Frame) {
     84     Frames.push_back(Frame);
     85   }
     86 };
     87 
     88 /// Container for description of a global variable.
     89 struct DIGlobal {
     90   std::string Name;
     91   uint64_t Start = 0;
     92   uint64_t Size = 0;
     93 
     94   DIGlobal() : Name("<invalid>") {}
     95 };
     96 
     97 /// A DINameKind is passed to name search methods to specify a
     98 /// preference regarding the type of name resolution the caller wants.
     99 enum class DINameKind { None, ShortName, LinkageName };
    100 
    101 /// Controls which fields of DILineInfo container should be filled
    102 /// with data.
    103 struct DILineInfoSpecifier {
    104   enum class FileLineInfoKind { None, Default, AbsoluteFilePath };
    105   using FunctionNameKind = DINameKind;
    106 
    107   FileLineInfoKind FLIKind;
    108   FunctionNameKind FNKind;
    109 
    110   DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default,
    111                       FunctionNameKind FNKind = FunctionNameKind::None)
    112       : FLIKind(FLIKind), FNKind(FNKind) {}
    113 };
    114 
    115 /// This is just a helper to programmatically construct DIDumpType.
    116 enum DIDumpTypeCounter {
    117 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
    118   DIDT_ID_##ENUM_NAME,
    119 #include "llvm/BinaryFormat/Dwarf.def"
    120 #undef HANDLE_DWARF_SECTION
    121   DIDT_ID_UUID,
    122   DIDT_ID_Count
    123 };
    124 static_assert(DIDT_ID_Count <= 32, "section types overflow storage");
    125 
    126 /// Selects which debug sections get dumped.
    127 enum DIDumpType : unsigned {
    128   DIDT_Null,
    129   DIDT_All             = ~0U,
    130 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
    131   DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
    132 #include "llvm/BinaryFormat/Dwarf.def"
    133 #undef HANDLE_DWARF_SECTION
    134   DIDT_UUID = 1 << DIDT_ID_UUID,
    135 };
    136 
    137 /// Container for dump options that control which debug information will be
    138 /// dumped.
    139 struct DIDumpOptions {
    140   unsigned DumpType = DIDT_All;
    141   unsigned RecurseDepth = -1U;
    142   bool ShowChildren = false;
    143   bool ShowParents = false;
    144   bool ShowForm = false;
    145   bool SummarizeTypes = false;
    146   bool Verbose = false;
    147 
    148   /// Return default option set for printing a single DIE without children.
    149   static DIDumpOptions getForSingleDIE() {
    150     DIDumpOptions Opts;
    151     Opts.RecurseDepth = 0;
    152     return Opts;
    153   }
    154 
    155   /// Return the options with RecurseDepth set to 0 unless explicitly required.
    156   DIDumpOptions noImplicitRecursion() const {
    157     DIDumpOptions Opts = *this;
    158     if (RecurseDepth == -1U && !ShowChildren)
    159       Opts.RecurseDepth = 0;
    160     return Opts;
    161   }
    162 };
    163 
    164 class DIContext {
    165 public:
    166   enum DIContextKind {
    167     CK_DWARF,
    168     CK_PDB
    169   };
    170 
    171   DIContext(DIContextKind K) : Kind(K) {}
    172   virtual ~DIContext() = default;
    173 
    174   DIContextKind getKind() const { return Kind; }
    175 
    176   virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
    177 
    178   virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) {
    179     // No verifier? Just say things went well.
    180     return true;
    181   }
    182 
    183   virtual DILineInfo getLineInfoForAddress(uint64_t Address,
    184       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
    185   virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address,
    186       uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
    187   virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
    188       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
    189 
    190 private:
    191   const DIContextKind Kind;
    192 };
    193 
    194 /// An inferface for inquiring the load address of a loaded object file
    195 /// to be used by the DIContext implementations when applying relocations
    196 /// on the fly.
    197 class LoadedObjectInfo {
    198 protected:
    199   LoadedObjectInfo() = default;
    200   LoadedObjectInfo(const LoadedObjectInfo &) = default;
    201 
    202 public:
    203   virtual ~LoadedObjectInfo() = default;
    204 
    205   /// Obtain the Load Address of a section by SectionRef.
    206   ///
    207   /// Calculate the address of the given section.
    208   /// The section need not be present in the local address space. The addresses
    209   /// need to be consistent with the addresses used to query the DIContext and
    210   /// the output of this function should be deterministic, i.e. repeated calls
    211   /// with the same Sec should give the same address.
    212   virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const {
    213     return 0;
    214   }
    215 
    216   /// If conveniently available, return the content of the given Section.
    217   ///
    218   /// When the section is available in the local address space, in relocated
    219   /// (loaded) form, e.g. because it was relocated by a JIT for execution, this
    220   /// function should provide the contents of said section in `Data`. If the
    221   /// loaded section is not available, or the cost of retrieving it would be
    222   /// prohibitive, this function should return false. In that case, relocations
    223   /// will be read from the local (unrelocated) object file and applied on the
    224   /// fly. Note that this method is used purely for optimzation purposes in the
    225   /// common case of JITting in the local address space, so returning false
    226   /// should always be correct.
    227   virtual bool getLoadedSectionContents(const object::SectionRef &Sec,
    228                                         StringRef &Data) const {
    229     return false;
    230   }
    231 
    232   // FIXME: This is untested and unused anywhere in the LLVM project, it's
    233   // used/needed by Julia (an external project). It should have some coverage
    234   // (at least tests, but ideally example functionality).
    235   /// Obtain a copy of this LoadedObjectInfo.
    236   virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0;
    237 };
    238 
    239 template <typename Derived, typename Base = LoadedObjectInfo>
    240 struct LoadedObjectInfoHelper : Base {
    241 protected:
    242   LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default;
    243   LoadedObjectInfoHelper() = default;
    244 
    245 public:
    246   template <typename... Ts>
    247   LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {}
    248 
    249   std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
    250     return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
    251   }
    252 };
    253 
    254 } // end namespace llvm
    255 
    256 #endif // LLVM_DEBUGINFO_DICONTEXT_H
    257