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