MCCodeView.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- MCCodeView.h - Machine Code CodeView support -------------*- 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. // Holds state from .cv_file and .cv_loc directives for later emission.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_MC_MCCODEVIEW_H
  18. #define LLVM_MC_MCCODEVIEW_H
  19. #include "llvm/ADT/ArrayRef.h"
  20. #include "llvm/ADT/DenseMap.h"
  21. #include "llvm/ADT/SmallVector.h"
  22. #include "llvm/ADT/StringMap.h"
  23. #include "llvm/ADT/StringRef.h"
  24. #include <map>
  25. #include <vector>
  26. namespace llvm {
  27. class MCAsmLayout;
  28. class MCCVDefRangeFragment;
  29. class MCCVInlineLineTableFragment;
  30. class MCDataFragment;
  31. class MCFragment;
  32. class MCSection;
  33. class MCSymbol;
  34. class MCContext;
  35. class MCObjectStreamer;
  36. class MCStreamer;
  37. /// Instances of this class represent the information from a
  38. /// .cv_loc directive.
  39. class MCCVLoc {
  40. const MCSymbol *Label = nullptr;
  41. uint32_t FunctionId;
  42. uint32_t FileNum;
  43. uint32_t Line;
  44. uint16_t Column;
  45. uint16_t PrologueEnd : 1;
  46. uint16_t IsStmt : 1;
  47. private: // CodeViewContext manages these
  48. friend class CodeViewContext;
  49. MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum,
  50. unsigned line, unsigned column, bool prologueend, bool isstmt)
  51. : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line),
  52. Column(column), PrologueEnd(prologueend), IsStmt(isstmt) {}
  53. // Allow the default copy constructor and assignment operator to be used
  54. // for an MCCVLoc object.
  55. public:
  56. const MCSymbol *getLabel() const { return Label; }
  57. unsigned getFunctionId() const { return FunctionId; }
  58. /// Get the FileNum of this MCCVLoc.
  59. unsigned getFileNum() const { return FileNum; }
  60. /// Get the Line of this MCCVLoc.
  61. unsigned getLine() const { return Line; }
  62. /// Get the Column of this MCCVLoc.
  63. unsigned getColumn() const { return Column; }
  64. bool isPrologueEnd() const { return PrologueEnd; }
  65. bool isStmt() const { return IsStmt; }
  66. void setLabel(const MCSymbol *L) { Label = L; }
  67. void setFunctionId(unsigned FID) { FunctionId = FID; }
  68. /// Set the FileNum of this MCCVLoc.
  69. void setFileNum(unsigned fileNum) { FileNum = fileNum; }
  70. /// Set the Line of this MCCVLoc.
  71. void setLine(unsigned line) { Line = line; }
  72. /// Set the Column of this MCCVLoc.
  73. void setColumn(unsigned column) {
  74. assert(column <= UINT16_MAX);
  75. Column = column;
  76. }
  77. void setPrologueEnd(bool PE) { PrologueEnd = PE; }
  78. void setIsStmt(bool IS) { IsStmt = IS; }
  79. };
  80. /// Information describing a function or inlined call site introduced by
  81. /// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc
  82. /// directives used with this function's id or the id of an inlined call site
  83. /// within this function or inlined call site.
  84. struct MCCVFunctionInfo {
  85. /// If this represents an inlined call site, then ParentFuncIdPlusOne will be
  86. /// the parent function id plus one. If this represents a normal function,
  87. /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel.
  88. /// If this struct is an unallocated slot in the function info vector, then
  89. /// ParentFuncIdPlusOne will be zero.
  90. unsigned ParentFuncIdPlusOne = 0;
  91. enum : unsigned { FunctionSentinel = ~0U };
  92. struct LineInfo {
  93. unsigned File;
  94. unsigned Line;
  95. unsigned Col;
  96. };
  97. LineInfo InlinedAt;
  98. /// The section of the first .cv_loc directive used for this function, or null
  99. /// if none has been seen yet.
  100. MCSection *Section = nullptr;
  101. /// Map from inlined call site id to the inlined at location to use for that
  102. /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h',
  103. /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both
  104. /// list the line info for the 'g' call site.
  105. DenseMap<unsigned, LineInfo> InlinedAtMap;
  106. /// Returns true if this is function info has not yet been used in a
  107. /// .cv_func_id or .cv_inline_site_id directive.
  108. bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; }
  109. /// Returns true if this represents an inlined call site, meaning
  110. /// ParentFuncIdPlusOne is neither zero nor ~0U.
  111. bool isInlinedCallSite() const {
  112. return !isUnallocatedFunctionInfo() &&
  113. ParentFuncIdPlusOne != FunctionSentinel;
  114. }
  115. unsigned getParentFuncId() const {
  116. assert(isInlinedCallSite());
  117. return ParentFuncIdPlusOne - 1;
  118. }
  119. };
  120. /// Holds state from .cv_file and .cv_loc directives for later emission.
  121. class CodeViewContext {
  122. public:
  123. CodeViewContext();
  124. ~CodeViewContext();
  125. bool isValidFileNumber(unsigned FileNumber) const;
  126. bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename,
  127. ArrayRef<uint8_t> ChecksumBytes, uint8_t ChecksumKind);
  128. /// Records the function id of a normal function. Returns false if the
  129. /// function id has already been used, and true otherwise.
  130. bool recordFunctionId(unsigned FuncId);
  131. /// Records the function id of an inlined call site. Records the "inlined at"
  132. /// location info of the call site, including what function or inlined call
  133. /// site it was inlined into. Returns false if the function id has already
  134. /// been used, and true otherwise.
  135. bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
  136. unsigned IAFile, unsigned IALine,
  137. unsigned IACol);
  138. /// Retreive the function info if this is a valid function id, or nullptr.
  139. MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId);
  140. /// Saves the information from the currently parsed .cv_loc directive
  141. /// and sets CVLocSeen. When the next instruction is assembled an entry
  142. /// in the line number table with this information and the address of the
  143. /// instruction will be created.
  144. void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId,
  145. unsigned FileNo, unsigned Line, unsigned Column,
  146. bool PrologueEnd, bool IsStmt);
  147. /// Add a line entry.
  148. void addLineEntry(const MCCVLoc &LineEntry);
  149. std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId);
  150. std::pair<size_t, size_t> getLineExtent(unsigned FuncId);
  151. ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R);
  152. /// Emits a line table substream.
  153. void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
  154. const MCSymbol *FuncBegin,
  155. const MCSymbol *FuncEnd);
  156. void emitInlineLineTableForFunction(MCObjectStreamer &OS,
  157. unsigned PrimaryFunctionId,
  158. unsigned SourceFileId,
  159. unsigned SourceLineNum,
  160. const MCSymbol *FnStartSym,
  161. const MCSymbol *FnEndSym);
  162. /// Encodes the binary annotations once we have a layout.
  163. void encodeInlineLineTable(MCAsmLayout &Layout,
  164. MCCVInlineLineTableFragment &F);
  165. MCFragment *
  166. emitDefRange(MCObjectStreamer &OS,
  167. ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
  168. StringRef FixedSizePortion);
  169. void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
  170. /// Emits the string table substream.
  171. void emitStringTable(MCObjectStreamer &OS);
  172. /// Emits the file checksum substream.
  173. void emitFileChecksums(MCObjectStreamer &OS);
  174. /// Emits the offset into the checksum table of the given file number.
  175. void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo);
  176. /// Add something to the string table. Returns the final string as well as
  177. /// offset into the string table.
  178. std::pair<StringRef, unsigned> addToStringTable(StringRef S);
  179. private:
  180. /// Map from string to string table offset.
  181. StringMap<unsigned> StringTable;
  182. /// The fragment that ultimately holds our strings.
  183. MCDataFragment *StrTabFragment = nullptr;
  184. bool InsertedStrTabFragment = false;
  185. MCDataFragment *getStringTableFragment();
  186. /// Get a string table offset.
  187. unsigned getStringTableOffset(StringRef S);
  188. struct FileInfo {
  189. unsigned StringTableOffset;
  190. // Indicates if this FileInfo corresponds to an actual file, or hasn't been
  191. // set yet.
  192. bool Assigned = false;
  193. uint8_t ChecksumKind;
  194. ArrayRef<uint8_t> Checksum;
  195. // Checksum offset stored as a symbol because it might be requested
  196. // before it has been calculated, so a fixup may be needed.
  197. MCSymbol *ChecksumTableOffset;
  198. };
  199. /// Array storing added file information.
  200. SmallVector<FileInfo, 4> Files;
  201. /// The offset of the first and last .cv_loc directive for a given function
  202. /// id.
  203. std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
  204. /// A collection of MCCVLoc for each section.
  205. std::vector<MCCVLoc> MCCVLines;
  206. /// All known functions and inlined call sites, indexed by function id.
  207. std::vector<MCCVFunctionInfo> Functions;
  208. /// Indicate whether we have already laid out the checksum table addresses or
  209. /// not.
  210. bool ChecksumOffsetsAssigned = false;
  211. };
  212. } // end namespace llvm
  213. #endif
  214. #ifdef __GNUC__
  215. #pragma GCC diagnostic pop
  216. #endif