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 27namespace llvm { 28 29class raw_ostream; 30 31/// A format-neutral container for source line information. 32struct 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 60using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>; 61 62/// A format-neutral container for inlined code description. 63class DIInliningInfo { 64 SmallVector<DILineInfo, 4> Frames; 65 66public: 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. 89struct 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. 99enum class DINameKind { None, ShortName, LinkageName }; 100 101/// Controls which fields of DILineInfo container should be filled 102/// with data. 103struct 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. 116enum 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}; 124static_assert(DIDT_ID_Count <= 32, "section types overflow storage"); 125 126/// Selects which debug sections get dumped. 127enum 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. 139struct 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 164class DIContext { 165public: 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 190private: 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. 197class LoadedObjectInfo { 198protected: 199 LoadedObjectInfo() = default; 200 LoadedObjectInfo(const LoadedObjectInfo &) = default; 201 202public: 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 239template <typename Derived, typename Base = LoadedObjectInfo> 240struct LoadedObjectInfoHelper : Base { 241protected: 242 LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default; 243 LoadedObjectInfoHelper() = default; 244 245public: 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