Line data Source code
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;
43 : MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum,
44 : unsigned line, unsigned column, bool prologueend, bool isstmt)
45 554 : : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line),
46 554 : 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:
52 0 : const MCSymbol *getLabel() const { return Label; }
53 :
54 0 : unsigned getFunctionId() const { return FunctionId; }
55 :
56 : /// Get the FileNum of this MCCVLoc.
57 0 : unsigned getFileNum() const { return FileNum; }
58 :
59 : /// Get the Line of this MCCVLoc.
60 0 : unsigned getLine() const { return Line; }
61 :
62 : /// Get the Column of this MCCVLoc.
63 18 : unsigned getColumn() const { return Column; }
64 :
65 : bool isPrologueEnd() const { return PrologueEnd; }
66 501 : bool isStmt() const { return IsStmt; }
67 :
68 0 : void setLabel(const MCSymbol *L) { Label = L; }
69 :
70 : void setFunctionId(unsigned FID) { FunctionId = FID; }
71 :
72 : /// Set the FileNum of this MCCVLoc.
73 0 : void setFileNum(unsigned fileNum) { FileNum = fileNum; }
74 :
75 : /// Set the Line of this MCCVLoc.
76 0 : void setLine(unsigned line) { Line = line; }
77 :
78 : /// Set the Column of this MCCVLoc.
79 : void setColumn(unsigned column) {
80 : assert(column <= UINT16_MAX);
81 : Column = column;
82 : }
83 :
84 : void setPrologueEnd(bool PE) { PrologueEnd = PE; }
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 1087 : 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.
122 0 : 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.
126 : bool isInlinedCallSite() const {
127 72 : return !isUnallocatedFunctionInfo() &&
128 : ParentFuncIdPlusOne != FunctionSentinel;
129 : }
130 :
131 0 : unsigned getParentFuncId() const {
132 : assert(isInlinedCallSite());
133 40 : 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 : void
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
|