DIContext.h 10 KB

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