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