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