xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/MC/MCCodeView.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Holds state from .cv_file and .cv_loc directives for later emission.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_MC_MCCODEVIEW_H
140b57cec5SDimitry Andric #define LLVM_MC_MCCODEVIEW_H
150b57cec5SDimitry Andric 
1681ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
1781ad6265SDimitry Andric #include "llvm/ADT/DenseMap.h"
1881ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
210b57cec5SDimitry Andric #include <map>
220b57cec5SDimitry Andric #include <vector>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace llvm {
25*0fca6ea1SDimitry Andric class MCAssembler;
2681ad6265SDimitry Andric class MCCVDefRangeFragment;
2781ad6265SDimitry Andric class MCCVInlineLineTableFragment;
2881ad6265SDimitry Andric class MCDataFragment;
2981ad6265SDimitry Andric class MCFragment;
3081ad6265SDimitry Andric class MCSection;
3181ad6265SDimitry Andric class MCSymbol;
320b57cec5SDimitry Andric class MCContext;
330b57cec5SDimitry Andric class MCObjectStreamer;
340b57cec5SDimitry Andric class MCStreamer;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric /// Instances of this class represent the information from a
370b57cec5SDimitry Andric /// .cv_loc directive.
380b57cec5SDimitry Andric class MCCVLoc {
390b57cec5SDimitry Andric   const MCSymbol *Label = nullptr;
400b57cec5SDimitry Andric   uint32_t FunctionId;
410b57cec5SDimitry Andric   uint32_t FileNum;
420b57cec5SDimitry Andric   uint32_t Line;
430b57cec5SDimitry Andric   uint16_t Column;
440b57cec5SDimitry Andric   uint16_t PrologueEnd : 1;
450b57cec5SDimitry Andric   uint16_t IsStmt : 1;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric private: // CodeViewContext manages these
480b57cec5SDimitry Andric   friend class CodeViewContext;
490b57cec5SDimitry Andric   MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum,
500b57cec5SDimitry Andric           unsigned line, unsigned column, bool prologueend, bool isstmt)
510b57cec5SDimitry Andric       : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line),
520b57cec5SDimitry Andric         Column(column), PrologueEnd(prologueend), IsStmt(isstmt) {}
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   // Allow the default copy constructor and assignment operator to be used
550b57cec5SDimitry Andric   // for an MCCVLoc object.
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric public:
580b57cec5SDimitry Andric   const MCSymbol *getLabel() const { return Label; }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   unsigned getFunctionId() const { return FunctionId; }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   /// Get the FileNum of this MCCVLoc.
630b57cec5SDimitry Andric   unsigned getFileNum() const { return FileNum; }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   /// Get the Line of this MCCVLoc.
660b57cec5SDimitry Andric   unsigned getLine() const { return Line; }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   /// Get the Column of this MCCVLoc.
690b57cec5SDimitry Andric   unsigned getColumn() const { return Column; }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   bool isPrologueEnd() const { return PrologueEnd; }
720b57cec5SDimitry Andric   bool isStmt() const { return IsStmt; }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   void setLabel(const MCSymbol *L) { Label = L; }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   void setFunctionId(unsigned FID) { FunctionId = FID; }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   /// Set the FileNum of this MCCVLoc.
790b57cec5SDimitry Andric   void setFileNum(unsigned fileNum) { FileNum = fileNum; }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   /// Set the Line of this MCCVLoc.
820b57cec5SDimitry Andric   void setLine(unsigned line) { Line = line; }
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   /// Set the Column of this MCCVLoc.
850b57cec5SDimitry Andric   void setColumn(unsigned column) {
860b57cec5SDimitry Andric     assert(column <= UINT16_MAX);
870b57cec5SDimitry Andric     Column = column;
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   void setPrologueEnd(bool PE) { PrologueEnd = PE; }
910b57cec5SDimitry Andric   void setIsStmt(bool IS) { IsStmt = IS; }
920b57cec5SDimitry Andric };
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric /// Information describing a function or inlined call site introduced by
950b57cec5SDimitry Andric /// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc
960b57cec5SDimitry Andric /// directives used with this function's id or the id of an inlined call site
970b57cec5SDimitry Andric /// within this function or inlined call site.
980b57cec5SDimitry Andric struct MCCVFunctionInfo {
990b57cec5SDimitry Andric   /// If this represents an inlined call site, then ParentFuncIdPlusOne will be
1000b57cec5SDimitry Andric   /// the parent function id plus one. If this represents a normal function,
1010b57cec5SDimitry Andric   /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel.
1020b57cec5SDimitry Andric   /// If this struct is an unallocated slot in the function info vector, then
1030b57cec5SDimitry Andric   /// ParentFuncIdPlusOne will be zero.
1040b57cec5SDimitry Andric   unsigned ParentFuncIdPlusOne = 0;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   enum : unsigned { FunctionSentinel = ~0U };
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   struct LineInfo {
1090b57cec5SDimitry Andric     unsigned File;
1100b57cec5SDimitry Andric     unsigned Line;
1110b57cec5SDimitry Andric     unsigned Col;
1120b57cec5SDimitry Andric   };
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   LineInfo InlinedAt;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   /// The section of the first .cv_loc directive used for this function, or null
1170b57cec5SDimitry Andric   /// if none has been seen yet.
1180b57cec5SDimitry Andric   MCSection *Section = nullptr;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   /// Map from inlined call site id to the inlined at location to use for that
1210b57cec5SDimitry Andric   /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h',
1220b57cec5SDimitry Andric   /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both
1230b57cec5SDimitry Andric   /// list the line info for the 'g' call site.
1240b57cec5SDimitry Andric   DenseMap<unsigned, LineInfo> InlinedAtMap;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   /// Returns true if this is function info has not yet been used in a
1270b57cec5SDimitry Andric   /// .cv_func_id or .cv_inline_site_id directive.
1280b57cec5SDimitry Andric   bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   /// Returns true if this represents an inlined call site, meaning
1310b57cec5SDimitry Andric   /// ParentFuncIdPlusOne is neither zero nor ~0U.
1320b57cec5SDimitry Andric   bool isInlinedCallSite() const {
1330b57cec5SDimitry Andric     return !isUnallocatedFunctionInfo() &&
1340b57cec5SDimitry Andric            ParentFuncIdPlusOne != FunctionSentinel;
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   unsigned getParentFuncId() const {
1380b57cec5SDimitry Andric     assert(isInlinedCallSite());
1390b57cec5SDimitry Andric     return ParentFuncIdPlusOne - 1;
1400b57cec5SDimitry Andric   }
1410b57cec5SDimitry Andric };
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric /// Holds state from .cv_file and .cv_loc directives for later emission.
1440b57cec5SDimitry Andric class CodeViewContext {
1450b57cec5SDimitry Andric public:
146*0fca6ea1SDimitry Andric   CodeViewContext(MCContext *MCCtx) : MCCtx(MCCtx) {}
1470b57cec5SDimitry Andric   ~CodeViewContext();
1480b57cec5SDimitry Andric 
14906c3fb27SDimitry Andric   CodeViewContext &operator=(const CodeViewContext &other) = delete;
15006c3fb27SDimitry Andric   CodeViewContext(const CodeViewContext &other) = delete;
15106c3fb27SDimitry Andric 
1520b57cec5SDimitry Andric   bool isValidFileNumber(unsigned FileNumber) const;
1530b57cec5SDimitry Andric   bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename,
1540b57cec5SDimitry Andric                ArrayRef<uint8_t> ChecksumBytes, uint8_t ChecksumKind);
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   /// Records the function id of a normal function. Returns false if the
1570b57cec5SDimitry Andric   /// function id has already been used, and true otherwise.
1580b57cec5SDimitry Andric   bool recordFunctionId(unsigned FuncId);
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   /// Records the function id of an inlined call site. Records the "inlined at"
1610b57cec5SDimitry Andric   /// location info of the call site, including what function or inlined call
1620b57cec5SDimitry Andric   /// site it was inlined into. Returns false if the function id has already
1630b57cec5SDimitry Andric   /// been used, and true otherwise.
1640b57cec5SDimitry Andric   bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
1650b57cec5SDimitry Andric                                unsigned IAFile, unsigned IALine,
1660b57cec5SDimitry Andric                                unsigned IACol);
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   /// Retreive the function info if this is a valid function id, or nullptr.
1690b57cec5SDimitry Andric   MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId);
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   /// Saves the information from the currently parsed .cv_loc directive
1720b57cec5SDimitry Andric   /// and sets CVLocSeen.  When the next instruction is assembled an entry
1730b57cec5SDimitry Andric   /// in the line number table with this information and the address of the
1740b57cec5SDimitry Andric   /// instruction will be created.
1750b57cec5SDimitry Andric   void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId,
1760b57cec5SDimitry Andric                    unsigned FileNo, unsigned Line, unsigned Column,
1770b57cec5SDimitry Andric                    bool PrologueEnd, bool IsStmt);
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   /// Add a line entry.
1800b57cec5SDimitry Andric   void addLineEntry(const MCCVLoc &LineEntry);
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId);
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   std::pair<size_t, size_t> getLineExtent(unsigned FuncId);
1855f757f3fSDimitry Andric   std::pair<size_t, size_t> getLineExtentIncludingInlinees(unsigned FuncId);
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R);
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   /// Emits a line table substream.
1900b57cec5SDimitry Andric   void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
1910b57cec5SDimitry Andric                                 const MCSymbol *FuncBegin,
1920b57cec5SDimitry Andric                                 const MCSymbol *FuncEnd);
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   void emitInlineLineTableForFunction(MCObjectStreamer &OS,
1950b57cec5SDimitry Andric                                       unsigned PrimaryFunctionId,
1960b57cec5SDimitry Andric                                       unsigned SourceFileId,
1970b57cec5SDimitry Andric                                       unsigned SourceLineNum,
1980b57cec5SDimitry Andric                                       const MCSymbol *FnStartSym,
1990b57cec5SDimitry Andric                                       const MCSymbol *FnEndSym);
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   /// Encodes the binary annotations once we have a layout.
202*0fca6ea1SDimitry Andric   void encodeInlineLineTable(const MCAssembler &Asm,
2030b57cec5SDimitry Andric                              MCCVInlineLineTableFragment &F);
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   MCFragment *
2060b57cec5SDimitry Andric   emitDefRange(MCObjectStreamer &OS,
2070b57cec5SDimitry Andric                ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
2080b57cec5SDimitry Andric                StringRef FixedSizePortion);
2090b57cec5SDimitry Andric 
210*0fca6ea1SDimitry Andric   void encodeDefRange(const MCAssembler &Asm, MCCVDefRangeFragment &F);
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   /// Emits the string table substream.
2130b57cec5SDimitry Andric   void emitStringTable(MCObjectStreamer &OS);
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   /// Emits the file checksum substream.
2160b57cec5SDimitry Andric   void emitFileChecksums(MCObjectStreamer &OS);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   /// Emits the offset into the checksum table of the given file number.
2190b57cec5SDimitry Andric   void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo);
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   /// Add something to the string table.  Returns the final string as well as
2220b57cec5SDimitry Andric   /// offset into the string table.
2230b57cec5SDimitry Andric   std::pair<StringRef, unsigned> addToStringTable(StringRef S);
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric private:
226*0fca6ea1SDimitry Andric   MCContext *MCCtx;
227*0fca6ea1SDimitry Andric 
2280b57cec5SDimitry Andric   /// Map from string to string table offset.
2290b57cec5SDimitry Andric   StringMap<unsigned> StringTable;
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   /// The fragment that ultimately holds our strings.
2320b57cec5SDimitry Andric   MCDataFragment *StrTabFragment = nullptr;
2330b57cec5SDimitry Andric   bool InsertedStrTabFragment = false;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   MCDataFragment *getStringTableFragment();
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   /// Get a string table offset.
2380b57cec5SDimitry Andric   unsigned getStringTableOffset(StringRef S);
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   struct FileInfo {
2410b57cec5SDimitry Andric     unsigned StringTableOffset;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric     // Indicates if this FileInfo corresponds to an actual file, or hasn't been
2440b57cec5SDimitry Andric     // set yet.
2450b57cec5SDimitry Andric     bool Assigned = false;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric     uint8_t ChecksumKind;
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric     ArrayRef<uint8_t> Checksum;
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric     // Checksum offset stored as a symbol because it might be requested
2520b57cec5SDimitry Andric     // before it has been calculated, so a fixup may be needed.
2530b57cec5SDimitry Andric     MCSymbol *ChecksumTableOffset;
2540b57cec5SDimitry Andric   };
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   /// Array storing added file information.
2570b57cec5SDimitry Andric   SmallVector<FileInfo, 4> Files;
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   /// The offset of the first and last .cv_loc directive for a given function
2600b57cec5SDimitry Andric   /// id.
2610b57cec5SDimitry Andric   std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   /// A collection of MCCVLoc for each section.
2640b57cec5SDimitry Andric   std::vector<MCCVLoc> MCCVLines;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   /// All known functions and inlined call sites, indexed by function id.
2670b57cec5SDimitry Andric   std::vector<MCCVFunctionInfo> Functions;
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   /// Indicate whether we have already laid out the checksum table addresses or
2700b57cec5SDimitry Andric   /// not.
2710b57cec5SDimitry Andric   bool ChecksumOffsetsAssigned = false;
2720b57cec5SDimitry Andric };
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric } // end namespace llvm
2750b57cec5SDimitry Andric #endif
276