Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:43

0001 //===-- LVCodeViewReader.h --------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines the LVCodeViewReader class, which is used to describe a
0010 // debug information (COFF) reader.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H
0015 #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H
0016 
0017 #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
0018 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
0019 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
0020 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
0021 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
0022 #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h"
0023 #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h"
0024 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
0025 #include "llvm/DebugInfo/PDB/PDB.h"
0026 #include "llvm/Support/BinaryByteStream.h"
0027 #include "llvm/Support/BinaryItemStream.h"
0028 #include "llvm/Support/BinaryStreamArray.h"
0029 
0030 namespace llvm {
0031 template <> struct BinaryItemTraits<codeview::CVType> {
0032   static size_t length(const codeview::CVType &Item) { return Item.length(); }
0033   static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) {
0034     return Item.data();
0035   }
0036 };
0037 
0038 namespace codeview {
0039 class LazyRandomTypeCollection;
0040 }
0041 namespace object {
0042 struct coff_section;
0043 }
0044 namespace pdb {
0045 class SymbolGroup;
0046 }
0047 namespace logicalview {
0048 
0049 class LVElement;
0050 class LVLine;
0051 class LVScope;
0052 class LVScopeCompileUnit;
0053 class LVSymbol;
0054 class LVType;
0055 class LVTypeVisitor;
0056 class LVSymbolVisitor;
0057 class LVSymbolVisitorDelegate;
0058 
0059 using LVNames = SmallVector<StringRef, 16>;
0060 
0061 // The DWARF reader uses the DWARF constants to create the logical elements.
0062 // The DW_TAG_* and DW_AT_* are used to select the logical object and to
0063 // set specific attributes, such as name, type, etc.
0064 // As the CodeView constants are different to the DWARF constants, the
0065 // CodeView reader will map them to the DWARF ones.
0066 
0067 class LVCodeViewReader final : public LVBinaryReader {
0068   friend class LVTypeVisitor;
0069   friend class LVSymbolVisitor;
0070   friend class LVSymbolVisitorDelegate;
0071 
0072   using LVModules = std::vector<LVScope *>;
0073   LVModules Modules;
0074 
0075   // Encapsulates access to the input file and any dependent type server,
0076   // including any precompiled header object.
0077   llvm::pdb::InputFile Input;
0078   std::shared_ptr<llvm::pdb::InputFile> TypeServer;
0079   std::shared_ptr<LazyRandomTypeCollection> PrecompHeader;
0080 
0081   // Persistance data when loading a type server.
0082   ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = nullptr;
0083   std::unique_ptr<MemoryBuffer> MemBuffer;
0084   std::unique_ptr<llvm::pdb::IPDBSession> Session;
0085   std::unique_ptr<llvm::pdb::NativeSession> PdbSession;
0086 
0087   // Persistance data when loading a precompiled header.
0088   BumpPtrAllocator BuilderAllocator;
0089   std::unique_ptr<AppendingTypeTableBuilder> Builder;
0090   std::unique_ptr<BinaryItemStream<CVType>> ItemStream;
0091   std::unique_ptr<BinaryStreamReader> ReaderPrecomp;
0092   std::vector<CVType> TypeArray;
0093   CVTypeArray TypeStream;
0094   CVTypeArray CVTypesPrecomp;
0095 
0096   // Persistance data when loading an executable file.
0097   std::unique_ptr<MemoryBuffer> BinaryBuffer;
0098   std::unique_ptr<llvm::object::Binary> BinaryExecutable;
0099 
0100   Error loadTargetInfo(const object::ObjectFile &Obj);
0101   Error loadTargetInfo(const llvm::pdb::PDBFile &Pdb);
0102 
0103   void mapRangeAddress(const object::ObjectFile &Obj,
0104                        const object::SectionRef &Section,
0105                        bool IsComdat) override;
0106 
0107   llvm::object::COFFObjectFile &getObj() { return Input.obj(); }
0108   llvm::pdb::PDBFile &getPdb() { return Input.pdb(); }
0109   bool isObj() const { return Input.isObj(); }
0110   bool isPdb() const { return Input.isPdb(); }
0111   StringRef getFileName() { return Input.getFilePath(); }
0112 
0113   // Pathname to executable image.
0114   std::string ExePath;
0115 
0116   LVOffset CurrentOffset = 0;
0117   int32_t CurrentModule = -1;
0118 
0119   using RelocMapTy = DenseMap<const llvm::object::coff_section *,
0120                               std::vector<llvm::object::RelocationRef>>;
0121   RelocMapTy RelocMap;
0122 
0123   // Object files have only one type stream that contains both types and ids.
0124   // Precompiled header objects don't contain an IPI stream. Use the TPI.
0125   LazyRandomTypeCollection &types() {
0126     return TypeServer ? TypeServer->types()
0127                       : (PrecompHeader ? *PrecompHeader : Input.types());
0128   }
0129   LazyRandomTypeCollection &ids() {
0130     return TypeServer ? TypeServer->ids()
0131                       : (PrecompHeader ? *PrecompHeader : Input.ids());
0132   }
0133 
0134   LVLogicalVisitor LogicalVisitor;
0135 
0136   Expected<StringRef>
0137   getFileNameForFileOffset(uint32_t FileOffset,
0138                            const llvm::pdb::SymbolGroup *SG = nullptr);
0139   void printRelocatedField(StringRef Label,
0140                            const llvm::object::coff_section *CoffSection,
0141                            uint32_t RelocOffset, uint32_t Offset,
0142                            StringRef *RelocSym);
0143 
0144   Error printFileNameForOffset(StringRef Label, uint32_t FileOffset,
0145                                const llvm::pdb::SymbolGroup *SG = nullptr);
0146 
0147   Error loadPrecompiledObject(PrecompRecord &Precomp, CVTypeArray &CVTypesObj);
0148   Error loadTypeServer(TypeServer2Record &TS);
0149   Error traverseTypes(llvm::pdb::PDBFile &Pdb, LazyRandomTypeCollection &Types,
0150                       LazyRandomTypeCollection &Ids);
0151 
0152   Error collectInlineeInfo(DebugInlineeLinesSubsectionRef &Lines,
0153                            const llvm::pdb::SymbolGroup *SG = nullptr);
0154 
0155   void cacheRelocations();
0156   Error resolveSymbol(const llvm::object::coff_section *CoffSection,
0157                       uint64_t Offset, llvm::object::SymbolRef &Sym);
0158   Error resolveSymbolName(const llvm::object::coff_section *CoffSection,
0159                           uint64_t Offset, StringRef &Name);
0160   Error traverseTypeSection(StringRef SectionName,
0161                             const llvm::object::SectionRef &Section);
0162   Error traverseSymbolSection(StringRef SectionName,
0163                               const llvm::object::SectionRef &Section);
0164   Error traverseInlineeLines(StringRef Subsection);
0165 
0166   DebugChecksumsSubsectionRef CVFileChecksumTable;
0167   DebugStringTableSubsectionRef CVStringTable;
0168 
0169   Error traverseSymbolsSubsection(StringRef Subsection,
0170                                   const llvm::object::SectionRef &Section,
0171                                   StringRef SectionContents);
0172 
0173   /// Given a .debug$S section, find the string table and file checksum table.
0174   /// This function taken from (COFFDumper.cpp).
0175   /// TODO: It can be moved to the COFF library.
0176   Error initializeFileAndStringTables(BinaryStreamReader &Reader);
0177 
0178   Error createLines(const FixedStreamArray<LineNumberEntry> &LineNumbers,
0179                     LVAddress Addendum, uint32_t Segment, uint32_t Begin,
0180                     uint32_t Size, uint32_t NameIndex,
0181                     const llvm::pdb::SymbolGroup *SG = nullptr);
0182   Error createScopes(llvm::object::COFFObjectFile &Obj);
0183   Error createScopes(llvm::pdb::PDBFile &Pdb);
0184   Error processModule();
0185 
0186 protected:
0187   Error createScopes() override;
0188   void sortScopes() override;
0189 
0190 public:
0191   LVCodeViewReader() = delete;
0192   LVCodeViewReader(StringRef Filename, StringRef FileFormatName,
0193                    llvm::object::COFFObjectFile &Obj, ScopedPrinter &W,
0194                    StringRef ExePath)
0195       : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF),
0196         Input(&Obj), ExePath(ExePath), LogicalVisitor(this, W, Input) {}
0197   LVCodeViewReader(StringRef Filename, StringRef FileFormatName,
0198                    llvm::pdb::PDBFile &Pdb, ScopedPrinter &W, StringRef ExePath)
0199       : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF),
0200         Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {}
0201   LVCodeViewReader(const LVCodeViewReader &) = delete;
0202   LVCodeViewReader &operator=(const LVCodeViewReader &) = delete;
0203   ~LVCodeViewReader() = default;
0204 
0205   void getLinkageName(const llvm::object::coff_section *CoffSection,
0206                       uint32_t RelocOffset, uint32_t Offset,
0207                       StringRef *RelocSym);
0208 
0209   void addModule(LVScope *Scope) { Modules.push_back(Scope); }
0210   LVScope *getScopeForModule(uint32_t Modi) {
0211     return Modi >= Modules.size() ? nullptr : Modules[Modi];
0212   }
0213 
0214   // Get the string representation for the CodeView symbols.
0215   static StringRef getSymbolKindName(SymbolKind Kind);
0216   static std::string formatRegisterId(RegisterId Register, CPUType CPU);
0217 
0218   std::string getRegisterName(LVSmall Opcode,
0219                               ArrayRef<uint64_t> Operands) override;
0220 
0221   bool isSystemEntry(LVElement *Element, StringRef Name) const override;
0222 
0223   void print(raw_ostream &OS) const;
0224   void printRecords(raw_ostream &OS) const override {
0225     LogicalVisitor.printRecords(OS);
0226   };
0227 
0228 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0229   void dump() const { print(dbgs()); }
0230 #endif
0231 };
0232 
0233 } // end namespace logicalview
0234 } // end namespace llvm
0235 
0236 #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H