blob: 5770f370341df8210433048aa8e0d83fb4be29ee [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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/StringMap.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/MC/MCFragment.h"
19#include "llvm/MC/MCObjectStreamer.h"
20#include <map>
21#include <vector>
22
23namespace llvm {
24class MCContext;
25class MCObjectStreamer;
26class MCStreamer;
27class CodeViewContext;
28
Andrew Scullcdfcccc2018-10-05 20:58:37 +010029/// Instances of this class represent the information from a
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010030/// .cv_loc directive.
31class MCCVLoc {
Andrew Scull0372a572018-11-16 15:47:06 +000032 const MCSymbol *Label = nullptr;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010033 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;
Andrew Scull0372a572018-11-16 15:47:06 +000042 MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum,
43 unsigned line, unsigned column, bool prologueend, bool isstmt)
44 : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line),
45 Column(column), PrologueEnd(prologueend), IsStmt(isstmt) {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010046
47 // Allow the default copy constructor and assignment operator to be used
48 // for an MCCVLoc object.
49
50public:
Andrew Scull0372a572018-11-16 15:47:06 +000051 const MCSymbol *getLabel() const { return Label; }
52
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010053 unsigned getFunctionId() const { return FunctionId; }
54
Andrew Scullcdfcccc2018-10-05 20:58:37 +010055 /// Get the FileNum of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010056 unsigned getFileNum() const { return FileNum; }
57
Andrew Scullcdfcccc2018-10-05 20:58:37 +010058 /// Get the Line of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010059 unsigned getLine() const { return Line; }
60
Andrew Scullcdfcccc2018-10-05 20:58:37 +010061 /// Get the Column of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010062 unsigned getColumn() const { return Column; }
63
64 bool isPrologueEnd() const { return PrologueEnd; }
65 bool isStmt() const { return IsStmt; }
66
Andrew Scull0372a572018-11-16 15:47:06 +000067 void setLabel(const MCSymbol *L) { Label = L; }
68
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010069 void setFunctionId(unsigned FID) { FunctionId = FID; }
70
Andrew Scullcdfcccc2018-10-05 20:58:37 +010071 /// Set the FileNum of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010072 void setFileNum(unsigned fileNum) { FileNum = fileNum; }
73
Andrew Scullcdfcccc2018-10-05 20:58:37 +010074 /// Set the Line of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010075 void setLine(unsigned line) { Line = line; }
76
Andrew Scullcdfcccc2018-10-05 20:58:37 +010077 /// Set the Column of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010078 void setColumn(unsigned column) {
79 assert(column <= UINT16_MAX);
80 Column = column;
81 }
82
83 void setPrologueEnd(bool PE) { PrologueEnd = PE; }
84 void setIsStmt(bool IS) { IsStmt = IS; }
85};
86
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010087/// Information describing a function or inlined call site introduced by
88/// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc
89/// directives used with this function's id or the id of an inlined call site
90/// within this function or inlined call site.
91struct MCCVFunctionInfo {
92 /// If this represents an inlined call site, then ParentFuncIdPlusOne will be
93 /// the parent function id plus one. If this represents a normal function,
94 /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel.
95 /// If this struct is an unallocated slot in the function info vector, then
96 /// ParentFuncIdPlusOne will be zero.
97 unsigned ParentFuncIdPlusOne = 0;
98
99 enum : unsigned { FunctionSentinel = ~0U };
100
101 struct LineInfo {
102 unsigned File;
103 unsigned Line;
104 unsigned Col;
105 };
106
107 LineInfo InlinedAt;
108
109 /// The section of the first .cv_loc directive used for this function, or null
110 /// if none has been seen yet.
111 MCSection *Section = nullptr;
112
113 /// Map from inlined call site id to the inlined at location to use for that
114 /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h',
115 /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both
116 /// list the line info for the 'g' call site.
117 DenseMap<unsigned, LineInfo> InlinedAtMap;
118
119 /// Returns true if this is function info has not yet been used in a
120 /// .cv_func_id or .cv_inline_site_id directive.
121 bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; }
122
123 /// Returns true if this represents an inlined call site, meaning
124 /// ParentFuncIdPlusOne is neither zero nor ~0U.
125 bool isInlinedCallSite() const {
126 return !isUnallocatedFunctionInfo() &&
127 ParentFuncIdPlusOne != FunctionSentinel;
128 }
129
130 unsigned getParentFuncId() const {
131 assert(isInlinedCallSite());
132 return ParentFuncIdPlusOne - 1;
133 }
134};
135
136/// Holds state from .cv_file and .cv_loc directives for later emission.
137class CodeViewContext {
138public:
139 CodeViewContext();
140 ~CodeViewContext();
141
142 bool isValidFileNumber(unsigned FileNumber) const;
143 bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename,
144 ArrayRef<uint8_t> ChecksumBytes, uint8_t ChecksumKind);
145
146 /// Records the function id of a normal function. Returns false if the
147 /// function id has already been used, and true otherwise.
148 bool recordFunctionId(unsigned FuncId);
149
150 /// Records the function id of an inlined call site. Records the "inlined at"
151 /// location info of the call site, including what function or inlined call
152 /// site it was inlined into. Returns false if the function id has already
153 /// been used, and true otherwise.
154 bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
155 unsigned IAFile, unsigned IALine,
156 unsigned IACol);
157
158 /// Retreive the function info if this is a valid function id, or nullptr.
159 MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId);
160
161 /// Saves the information from the currently parsed .cv_loc directive
162 /// and sets CVLocSeen. When the next instruction is assembled an entry
163 /// in the line number table with this information and the address of the
164 /// instruction will be created.
Andrew Scull0372a572018-11-16 15:47:06 +0000165 void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId,
166 unsigned FileNo, unsigned Line, unsigned Column,
167 bool PrologueEnd, bool IsStmt);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100168
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100169 /// Add a line entry.
Andrew Scull0372a572018-11-16 15:47:06 +0000170 void addLineEntry(const MCCVLoc &LineEntry);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100171
Andrew Scull0372a572018-11-16 15:47:06 +0000172 std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100173
174 std::pair<size_t, size_t> getLineExtent(unsigned FuncId);
175
Andrew Scull0372a572018-11-16 15:47:06 +0000176 ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100177
178 /// Emits a line table substream.
179 void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
180 const MCSymbol *FuncBegin,
181 const MCSymbol *FuncEnd);
182
183 void emitInlineLineTableForFunction(MCObjectStreamer &OS,
184 unsigned PrimaryFunctionId,
185 unsigned SourceFileId,
186 unsigned SourceLineNum,
187 const MCSymbol *FnStartSym,
188 const MCSymbol *FnEndSym);
189
190 /// Encodes the binary annotations once we have a layout.
191 void encodeInlineLineTable(MCAsmLayout &Layout,
192 MCCVInlineLineTableFragment &F);
193
Andrew Walbran16937d02019-10-22 13:54:20 +0100194 MCFragment *
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100195 emitDefRange(MCObjectStreamer &OS,
196 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
197 StringRef FixedSizePortion);
198
199 void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
200
201 /// Emits the string table substream.
202 void emitStringTable(MCObjectStreamer &OS);
203
204 /// Emits the file checksum substream.
205 void emitFileChecksums(MCObjectStreamer &OS);
206
207 /// Emits the offset into the checksum table of the given file number.
208 void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo);
209
210 /// Add something to the string table. Returns the final string as well as
211 /// offset into the string table.
212 std::pair<StringRef, unsigned> addToStringTable(StringRef S);
213
214private:
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100215 /// Map from string to string table offset.
216 StringMap<unsigned> StringTable;
217
218 /// The fragment that ultimately holds our strings.
219 MCDataFragment *StrTabFragment = nullptr;
220 bool InsertedStrTabFragment = false;
221
222 MCDataFragment *getStringTableFragment();
223
224 /// Get a string table offset.
225 unsigned getStringTableOffset(StringRef S);
226
227 struct FileInfo {
228 unsigned StringTableOffset;
229
230 // Indicates if this FileInfo corresponds to an actual file, or hasn't been
231 // set yet.
232 bool Assigned = false;
233
234 uint8_t ChecksumKind;
235
236 ArrayRef<uint8_t> Checksum;
237
238 // Checksum offset stored as a symbol because it might be requested
239 // before it has been calculated, so a fixup may be needed.
240 MCSymbol *ChecksumTableOffset;
241 };
242
243 /// Array storing added file information.
244 SmallVector<FileInfo, 4> Files;
245
246 /// The offset of the first and last .cv_loc directive for a given function
247 /// id.
248 std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
249
Andrew Scull0372a572018-11-16 15:47:06 +0000250 /// A collection of MCCVLoc for each section.
251 std::vector<MCCVLoc> MCCVLines;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100252
253 /// All known functions and inlined call sites, indexed by function id.
254 std::vector<MCCVFunctionInfo> Functions;
255
256 /// Indicate whether we have already laid out the checksum table addresses or
257 /// not.
258 bool ChecksumOffsetsAssigned = false;
259};
260
261} // end namespace llvm
262#endif