DIContext.h 10 KB

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