123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // Holds state from .cv_file and .cv_loc directives for later emission.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_MC_MCCODEVIEW_H
- #define LLVM_MC_MCCODEVIEW_H
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringMap.h"
- #include "llvm/ADT/StringRef.h"
- #include <map>
- #include <vector>
- namespace llvm {
- class MCAsmLayout;
- class MCCVDefRangeFragment;
- class MCCVInlineLineTableFragment;
- class MCDataFragment;
- class MCFragment;
- class MCSection;
- class MCSymbol;
- class MCContext;
- class MCObjectStreamer;
- class MCStreamer;
- /// Instances of this class represent the information from a
- /// .cv_loc directive.
- class MCCVLoc {
- const MCSymbol *Label = nullptr;
- uint32_t FunctionId;
- uint32_t FileNum;
- uint32_t Line;
- uint16_t Column;
- uint16_t PrologueEnd : 1;
- uint16_t IsStmt : 1;
- private: // CodeViewContext manages these
- friend class CodeViewContext;
- MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum,
- unsigned line, unsigned column, bool prologueend, bool isstmt)
- : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line),
- Column(column), PrologueEnd(prologueend), IsStmt(isstmt) {}
- // Allow the default copy constructor and assignment operator to be used
- // for an MCCVLoc object.
- public:
- const MCSymbol *getLabel() const { return Label; }
- unsigned getFunctionId() const { return FunctionId; }
- /// Get the FileNum of this MCCVLoc.
- unsigned getFileNum() const { return FileNum; }
- /// Get the Line of this MCCVLoc.
- unsigned getLine() const { return Line; }
- /// Get the Column of this MCCVLoc.
- unsigned getColumn() const { return Column; }
- bool isPrologueEnd() const { return PrologueEnd; }
- bool isStmt() const { return IsStmt; }
- void setLabel(const MCSymbol *L) { Label = L; }
- void setFunctionId(unsigned FID) { FunctionId = FID; }
- /// Set the FileNum of this MCCVLoc.
- void setFileNum(unsigned fileNum) { FileNum = fileNum; }
- /// Set the Line of this MCCVLoc.
- void setLine(unsigned line) { Line = line; }
- /// Set the Column of this MCCVLoc.
- void setColumn(unsigned column) {
- assert(column <= UINT16_MAX);
- Column = column;
- }
- void setPrologueEnd(bool PE) { PrologueEnd = PE; }
- void setIsStmt(bool IS) { IsStmt = IS; }
- };
- /// Information describing a function or inlined call site introduced by
- /// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc
- /// directives used with this function's id or the id of an inlined call site
- /// within this function or inlined call site.
- struct MCCVFunctionInfo {
- /// If this represents an inlined call site, then ParentFuncIdPlusOne will be
- /// the parent function id plus one. If this represents a normal function,
- /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel.
- /// If this struct is an unallocated slot in the function info vector, then
- /// ParentFuncIdPlusOne will be zero.
- unsigned ParentFuncIdPlusOne = 0;
- enum : unsigned { FunctionSentinel = ~0U };
- struct LineInfo {
- unsigned File;
- unsigned Line;
- unsigned Col;
- };
- LineInfo InlinedAt;
- /// The section of the first .cv_loc directive used for this function, or null
- /// if none has been seen yet.
- MCSection *Section = nullptr;
- /// Map from inlined call site id to the inlined at location to use for that
- /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h',
- /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both
- /// list the line info for the 'g' call site.
- DenseMap<unsigned, LineInfo> InlinedAtMap;
- /// Returns true if this is function info has not yet been used in a
- /// .cv_func_id or .cv_inline_site_id directive.
- bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; }
- /// Returns true if this represents an inlined call site, meaning
- /// ParentFuncIdPlusOne is neither zero nor ~0U.
- bool isInlinedCallSite() const {
- return !isUnallocatedFunctionInfo() &&
- ParentFuncIdPlusOne != FunctionSentinel;
- }
- unsigned getParentFuncId() const {
- assert(isInlinedCallSite());
- return ParentFuncIdPlusOne - 1;
- }
- };
- /// Holds state from .cv_file and .cv_loc directives for later emission.
- class CodeViewContext {
- public:
- CodeViewContext();
- ~CodeViewContext();
- bool isValidFileNumber(unsigned FileNumber) const;
- bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename,
- ArrayRef<uint8_t> ChecksumBytes, uint8_t ChecksumKind);
- /// Records the function id of a normal function. Returns false if the
- /// function id has already been used, and true otherwise.
- bool recordFunctionId(unsigned FuncId);
- /// Records the function id of an inlined call site. Records the "inlined at"
- /// location info of the call site, including what function or inlined call
- /// site it was inlined into. Returns false if the function id has already
- /// been used, and true otherwise.
- bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
- unsigned IAFile, unsigned IALine,
- unsigned IACol);
- /// Retreive the function info if this is a valid function id, or nullptr.
- MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId);
- /// Saves the information from the currently parsed .cv_loc directive
- /// and sets CVLocSeen. When the next instruction is assembled an entry
- /// in the line number table with this information and the address of the
- /// instruction will be created.
- void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId,
- unsigned FileNo, unsigned Line, unsigned Column,
- bool PrologueEnd, bool IsStmt);
- /// Add a line entry.
- void addLineEntry(const MCCVLoc &LineEntry);
- std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId);
- std::pair<size_t, size_t> getLineExtent(unsigned FuncId);
- ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R);
- /// Emits a line table substream.
- void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
- const MCSymbol *FuncBegin,
- const MCSymbol *FuncEnd);
- void emitInlineLineTableForFunction(MCObjectStreamer &OS,
- unsigned PrimaryFunctionId,
- unsigned SourceFileId,
- unsigned SourceLineNum,
- const MCSymbol *FnStartSym,
- const MCSymbol *FnEndSym);
- /// Encodes the binary annotations once we have a layout.
- void encodeInlineLineTable(MCAsmLayout &Layout,
- MCCVInlineLineTableFragment &F);
- MCFragment *
- emitDefRange(MCObjectStreamer &OS,
- ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
- StringRef FixedSizePortion);
- void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
- /// Emits the string table substream.
- void emitStringTable(MCObjectStreamer &OS);
- /// Emits the file checksum substream.
- void emitFileChecksums(MCObjectStreamer &OS);
- /// Emits the offset into the checksum table of the given file number.
- void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo);
- /// Add something to the string table. Returns the final string as well as
- /// offset into the string table.
- std::pair<StringRef, unsigned> addToStringTable(StringRef S);
- private:
- /// Map from string to string table offset.
- StringMap<unsigned> StringTable;
- /// The fragment that ultimately holds our strings.
- MCDataFragment *StrTabFragment = nullptr;
- bool InsertedStrTabFragment = false;
- MCDataFragment *getStringTableFragment();
- /// Get a string table offset.
- unsigned getStringTableOffset(StringRef S);
- struct FileInfo {
- unsigned StringTableOffset;
- // Indicates if this FileInfo corresponds to an actual file, or hasn't been
- // set yet.
- bool Assigned = false;
- uint8_t ChecksumKind;
- ArrayRef<uint8_t> Checksum;
- // Checksum offset stored as a symbol because it might be requested
- // before it has been calculated, so a fixup may be needed.
- MCSymbol *ChecksumTableOffset;
- };
- /// Array storing added file information.
- SmallVector<FileInfo, 4> Files;
- /// The offset of the first and last .cv_loc directive for a given function
- /// id.
- std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
- /// A collection of MCCVLoc for each section.
- std::vector<MCCVLoc> MCCVLines;
- /// All known functions and inlined call sites, indexed by function id.
- std::vector<MCCVFunctionInfo> Functions;
- /// Indicate whether we have already laid out the checksum table addresses or
- /// not.
- bool ChecksumOffsetsAssigned = false;
- };
- } // end namespace llvm
- #endif
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|