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 /// DILineInfo - 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 typedef SmallVector<std::pair<uint64_t, DILineInfo>, 16> DILineInfoTable; 61 62 /// DIInliningInfo - 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 /// DIGlobal - 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 /// DILineInfoSpecifier - controls which fields of DILineInfo container 102 /// should be filled with data. 103 struct DILineInfoSpecifier { 104 enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; 105 typedef DINameKind FunctionNameKind; 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 /// Selects which debug sections get dumped. 116 enum DIDumpType { 117 DIDT_Null, 118 DIDT_All, 119 DIDT_Abbrev, 120 DIDT_AbbrevDwo, 121 DIDT_Aranges, 122 DIDT_Frames, 123 DIDT_Info, 124 DIDT_InfoDwo, 125 DIDT_Types, 126 DIDT_TypesDwo, 127 DIDT_Line, 128 DIDT_LineDwo, 129 DIDT_Loc, 130 DIDT_LocDwo, 131 DIDT_Macro, 132 DIDT_Ranges, 133 DIDT_Pubnames, 134 DIDT_Pubtypes, 135 DIDT_GnuPubnames, 136 DIDT_GnuPubtypes, 137 DIDT_Str, 138 DIDT_StrDwo, 139 DIDT_StrOffsetsDwo, 140 DIDT_AppleNames, 141 DIDT_AppleTypes, 142 DIDT_AppleNamespaces, 143 DIDT_AppleObjC, 144 DIDT_CUIndex, 145 DIDT_GdbIndex, 146 DIDT_TUIndex, 147 }; 148 149 class DIContext { 150 public: 151 enum DIContextKind { 152 CK_DWARF, 153 CK_PDB 154 }; 155 156 DIContext(DIContextKind K) : Kind(K) {} 157 virtual ~DIContext() = default; 158 159 DIContextKind getKind() const { return Kind; } 160 161 virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All, 162 bool DumpEH = false, bool SummarizeTypes = false) = 0; 163 164 virtual DILineInfo getLineInfoForAddress(uint64_t Address, 165 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; 166 virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, 167 uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; 168 virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, 169 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; 170 171 private: 172 const DIContextKind Kind; 173 }; 174 175 /// An inferface for inquiring the load address of a loaded object file 176 /// to be used by the DIContext implementations when applying relocations 177 /// on the fly. 178 class LoadedObjectInfo { 179 protected: 180 LoadedObjectInfo() = default; 181 LoadedObjectInfo(const LoadedObjectInfo &) = default; 182 183 public: 184 virtual ~LoadedObjectInfo() = default; 185 186 /// Obtain the Load Address of a section by SectionRef. 187 /// 188 /// Calculate the address of the given section. 189 /// The section need not be present in the local address space. The addresses 190 /// need to be consistent with the addresses used to query the DIContext and 191 /// the output of this function should be deterministic, i.e. repeated calls with 192 /// the same Sec should give the same address. 193 virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const = 0; 194 195 /// If conveniently available, return the content of the given Section. 196 /// 197 /// When the section is available in the local address space, in relocated (loaded) 198 /// form, e.g. because it was relocated by a JIT for execution, this function 199 /// should provide the contents of said section in `Data`. If the loaded section 200 /// is not available, or the cost of retrieving it would be prohibitive, this 201 /// function should return false. In that case, relocations will be read from the 202 /// local (unrelocated) object file and applied on the fly. Note that this method 203 /// is used purely for optimzation purposes in the common case of JITting in the 204 /// local address space, so returning false should always be correct. 205 virtual bool getLoadedSectionContents(const object::SectionRef &Sec, 206 StringRef &Data) const { 207 return false; 208 } 209 210 /// Obtain a copy of this LoadedObjectInfo. 211 /// 212 /// The caller is responsible for deallocation once the copy is no longer required. 213 virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0; 214 }; 215 216 } // end namespace llvm 217 218 #endif // LLVM_DEBUGINFO_DICONTEXT_H 219