DIContext.h 11 KB

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