DIContext.h 10 KB

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