• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/StringRef.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/MC/MCObjectStreamer.h"
20 #include "llvm/MC/MCFragment.h"
21 #include <map>
22 #include <vector>
23 
24 namespace llvm {
25 class MCContext;
26 class MCObjectStreamer;
27 class MCStreamer;
28 
29 /// \brief Instances of this class represent the information from a
30 /// .cv_loc directive.
31 class MCCVLoc {
32   uint32_t FunctionId;
33   uint32_t FileNum;
34   uint32_t Line;
35   uint16_t Column;
36   uint16_t PrologueEnd : 1;
37   uint16_t IsStmt : 1;
38 
39 private: // MCContext manages these
40   friend class MCContext;
MCCVLoc(unsigned functionid,unsigned fileNum,unsigned line,unsigned column,bool prologueend,bool isstmt)41   MCCVLoc(unsigned functionid, unsigned fileNum, unsigned line, unsigned column,
42           bool prologueend, bool isstmt)
43       : FunctionId(functionid), FileNum(fileNum), Line(line), Column(column),
44         PrologueEnd(prologueend), IsStmt(isstmt) {}
45 
46   // Allow the default copy constructor and assignment operator to be used
47   // for an MCCVLoc object.
48 
49 public:
getFunctionId()50   unsigned getFunctionId() const { return FunctionId; }
51 
52   /// \brief Get the FileNum of this MCCVLoc.
getFileNum()53   unsigned getFileNum() const { return FileNum; }
54 
55   /// \brief Get the Line of this MCCVLoc.
getLine()56   unsigned getLine() const { return Line; }
57 
58   /// \brief Get the Column of this MCCVLoc.
getColumn()59   unsigned getColumn() const { return Column; }
60 
isPrologueEnd()61   bool isPrologueEnd() const { return PrologueEnd; }
isStmt()62   bool isStmt() const { return IsStmt; }
63 
setFunctionId(unsigned FID)64   void setFunctionId(unsigned FID) { FunctionId = FID; }
65 
66   /// \brief Set the FileNum of this MCCVLoc.
setFileNum(unsigned fileNum)67   void setFileNum(unsigned fileNum) { FileNum = fileNum; }
68 
69   /// \brief Set the Line of this MCCVLoc.
setLine(unsigned line)70   void setLine(unsigned line) { Line = line; }
71 
72   /// \brief Set the Column of this MCCVLoc.
setColumn(unsigned column)73   void setColumn(unsigned column) {
74     assert(column <= UINT16_MAX);
75     Column = column;
76   }
77 
setPrologueEnd(bool PE)78   void setPrologueEnd(bool PE) { PrologueEnd = PE; }
setIsStmt(bool IS)79   void setIsStmt(bool IS) { IsStmt = IS; }
80 };
81 
82 /// \brief Instances of this class represent the line information for
83 /// the CodeView line table entries.  Which is created after a machine
84 /// instruction is assembled and uses an address from a temporary label
85 /// created at the current address in the current section and the info from
86 /// the last .cv_loc directive seen as stored in the context.
87 class MCCVLineEntry : public MCCVLoc {
88   const MCSymbol *Label;
89 
90 private:
91   // Allow the default copy constructor and assignment operator to be used
92   // for an MCCVLineEntry object.
93 
94 public:
95   // Constructor to create an MCCVLineEntry given a symbol and the dwarf loc.
MCCVLineEntry(const MCSymbol * Label,const MCCVLoc loc)96   MCCVLineEntry(const MCSymbol *Label, const MCCVLoc loc)
97       : MCCVLoc(loc), Label(Label) {}
98 
getLabel()99   const MCSymbol *getLabel() const { return Label; }
100 
101   // This is called when an instruction is assembled into the specified
102   // section and if there is information from the last .cv_loc directive that
103   // has yet to have a line entry made for it is made.
104   static void Make(MCObjectStreamer *MCOS);
105 };
106 
107 /// Holds state from .cv_file and .cv_loc directives for later emission.
108 class CodeViewContext {
109 public:
110   CodeViewContext();
111   ~CodeViewContext();
112 
113   bool isValidFileNumber(unsigned FileNumber) const;
114   bool addFile(unsigned FileNumber, StringRef Filename);
getFilenames()115   ArrayRef<StringRef> getFilenames() { return Filenames; }
116 
117   /// \brief Add a line entry.
addLineEntry(const MCCVLineEntry & LineEntry)118   void addLineEntry(const MCCVLineEntry &LineEntry) {
119     size_t Offset = MCCVLines.size();
120     auto I = MCCVLineStartStop.insert(
121         {LineEntry.getFunctionId(), {Offset, Offset + 1}});
122     if (!I.second)
123       I.first->second.second = Offset + 1;
124     MCCVLines.push_back(LineEntry);
125   }
126 
getFunctionLineEntries(unsigned FuncId)127   std::vector<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId) {
128     std::vector<MCCVLineEntry> FilteredLines;
129 
130     auto I = MCCVLineStartStop.find(FuncId);
131     if (I != MCCVLineStartStop.end())
132       for (size_t Idx = I->second.first, End = I->second.second; Idx != End;
133            ++Idx)
134         if (MCCVLines[Idx].getFunctionId() == FuncId)
135           FilteredLines.push_back(MCCVLines[Idx]);
136     return FilteredLines;
137   }
138 
getLineExtent(unsigned FuncId)139   std::pair<size_t, size_t> getLineExtent(unsigned FuncId) {
140     auto I = MCCVLineStartStop.find(FuncId);
141     // Return an empty extent if there are no cv_locs for this function id.
142     if (I == MCCVLineStartStop.end())
143       return {~0ULL, 0};
144     return I->second;
145   }
146 
getLinesForExtent(size_t L,size_t R)147   ArrayRef<MCCVLineEntry> getLinesForExtent(size_t L, size_t R) {
148     if (R <= L)
149       return None;
150     if (L >= MCCVLines.size())
151       return None;
152     return makeArrayRef(&MCCVLines[L], R - L);
153   }
154 
155   /// Emits a line table substream.
156   void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
157                                 const MCSymbol *FuncBegin,
158                                 const MCSymbol *FuncEnd);
159 
160   void emitInlineLineTableForFunction(
161       MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
162       unsigned SourceLineNum, const MCSymbol *FnStartSym,
163       const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds);
164 
165   /// Encodes the binary annotations once we have a layout.
166   void encodeInlineLineTable(MCAsmLayout &Layout,
167                              MCCVInlineLineTableFragment &F);
168 
169   void
170   emitDefRange(MCObjectStreamer &OS,
171                ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
172                StringRef FixedSizePortion);
173 
174   void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
175 
176   /// Emits the string table substream.
177   void emitStringTable(MCObjectStreamer &OS);
178 
179   /// Emits the file checksum substream.
180   void emitFileChecksums(MCObjectStreamer &OS);
181 
182 private:
183   /// Map from string to string table offset.
184   StringMap<unsigned> StringTable;
185 
186   /// The fragment that ultimately holds our strings.
187   MCDataFragment *StrTabFragment = nullptr;
188   bool InsertedStrTabFragment = false;
189 
190   MCDataFragment *getStringTableFragment();
191 
192   /// Add something to the string table.
193   StringRef addToStringTable(StringRef S);
194 
195   /// Get a string table offset.
196   unsigned getStringTableOffset(StringRef S);
197 
198   /// An array of absolute paths. Eventually this may include the file checksum.
199   SmallVector<StringRef, 4> Filenames;
200 
201   /// The offset of the first and last .cv_loc directive for a given function
202   /// id.
203   std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
204 
205   /// A collection of MCCVLineEntry for each section.
206   std::vector<MCCVLineEntry> MCCVLines;
207 };
208 
209 } // end namespace llvm
210 #endif
211