| //===-- LVCodeViewReader.h --------------------------------------*- 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 |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the LVCodeViewReader class, which is used to describe a |
| // debug information (COFF) reader. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H |
| #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H |
| |
| #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h" |
| #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" |
| #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" |
| #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" |
| #include "llvm/DebugInfo/CodeView/TypeRecord.h" |
| #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h" |
| #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h" |
| #include "llvm/DebugInfo/PDB/Native/NativeSession.h" |
| #include "llvm/DebugInfo/PDB/PDB.h" |
| #include "llvm/Support/BinaryByteStream.h" |
| #include "llvm/Support/BinaryItemStream.h" |
| #include "llvm/Support/BinaryStreamArray.h" |
| |
| namespace llvm { |
| template <> struct BinaryItemTraits<codeview::CVType> { |
| static size_t length(const codeview::CVType &Item) { return Item.length(); } |
| static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) { |
| return Item.data(); |
| } |
| }; |
| |
| namespace codeview { |
| class LazyRandomTypeCollection; |
| } |
| namespace object { |
| struct coff_section; |
| } |
| namespace pdb { |
| class SymbolGroup; |
| } |
| namespace logicalview { |
| |
| class LVElement; |
| class LVLine; |
| class LVScope; |
| class LVScopeCompileUnit; |
| class LVSymbol; |
| class LVType; |
| class LVTypeVisitor; |
| class LVSymbolVisitor; |
| class LVSymbolVisitorDelegate; |
| |
| using LVNames = SmallVector<StringRef, 16>; |
| |
| // The ELF reader uses the DWARF constants to create the logical elements. |
| // The DW_TAG_* and DW_AT_* are used to select the logical object and to |
| // set specific attributes, such as name, type, etc. |
| // As the CodeView constants are different to the DWARF constants, the |
| // CodeView reader will map them to the DWARF ones. |
| |
| class LVCodeViewReader final : public LVBinaryReader { |
| friend class LVTypeVisitor; |
| friend class LVSymbolVisitor; |
| friend class LVSymbolVisitorDelegate; |
| |
| using LVModules = std::vector<LVScope *>; |
| LVModules Modules; |
| |
| // Encapsulates access to the input file and any dependent type server, |
| // including any precompiled header object. |
| llvm::pdb::InputFile Input; |
| std::shared_ptr<llvm::pdb::InputFile> TypeServer; |
| std::shared_ptr<LazyRandomTypeCollection> PrecompHeader; |
| |
| // Persistance data when loading a type server. |
| ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = nullptr; |
| std::unique_ptr<MemoryBuffer> MemBuffer; |
| std::unique_ptr<llvm::pdb::IPDBSession> Session; |
| std::unique_ptr<llvm::pdb::NativeSession> PdbSession; |
| |
| // Persistance data when loading a precompiled header. |
| BumpPtrAllocator BuilderAllocator; |
| std::unique_ptr<AppendingTypeTableBuilder> Builder; |
| std::unique_ptr<BinaryItemStream<CVType>> ItemStream; |
| std::unique_ptr<BinaryStreamReader> ReaderPrecomp; |
| std::vector<CVType> TypeArray; |
| CVTypeArray TypeStream; |
| CVTypeArray CVTypesPrecomp; |
| |
| // Persistance data when loading an executable file. |
| std::unique_ptr<MemoryBuffer> BinaryBuffer; |
| std::unique_ptr<llvm::object::Binary> BinaryExecutable; |
| |
| Error loadTargetInfo(const object::ObjectFile &Obj); |
| Error loadTargetInfo(const llvm::pdb::PDBFile &Pdb); |
| |
| void mapRangeAddress(const object::ObjectFile &Obj, |
| const object::SectionRef &Section, |
| bool IsComdat) override; |
| |
| llvm::object::COFFObjectFile &getObj() { return Input.obj(); } |
| llvm::pdb::PDBFile &getPdb() { return Input.pdb(); } |
| bool isObj() const { return Input.isObj(); } |
| bool isPdb() const { return Input.isPdb(); } |
| StringRef getFileName() { return Input.getFilePath(); } |
| |
| // Pathname to executable image. |
| std::string ExePath; |
| |
| LVOffset CurrentOffset = 0; |
| int32_t CurrentModule = -1; |
| |
| using RelocMapTy = DenseMap<const llvm::object::coff_section *, |
| std::vector<llvm::object::RelocationRef>>; |
| RelocMapTy RelocMap; |
| |
| // Object files have only one type stream that contains both types and ids. |
| // Precompiled header objects don't contain an IPI stream. Use the TPI. |
| LazyRandomTypeCollection &types() { |
| return TypeServer ? TypeServer->types() |
| : (PrecompHeader ? *PrecompHeader : Input.types()); |
| } |
| LazyRandomTypeCollection &ids() { |
| return TypeServer ? TypeServer->ids() |
| : (PrecompHeader ? *PrecompHeader : Input.ids()); |
| } |
| |
| LVLogicalVisitor LogicalVisitor; |
| |
| Expected<StringRef> |
| getFileNameForFileOffset(uint32_t FileOffset, |
| const llvm::pdb::SymbolGroup *SG = nullptr); |
| void printRelocatedField(StringRef Label, |
| const llvm::object::coff_section *CoffSection, |
| uint32_t RelocOffset, uint32_t Offset, |
| StringRef *RelocSym); |
| |
| Error printFileNameForOffset(StringRef Label, uint32_t FileOffset, |
| const llvm::pdb::SymbolGroup *SG = nullptr); |
| |
| Error loadPrecompiledObject(PrecompRecord &Precomp, CVTypeArray &CVTypesObj); |
| Error loadTypeServer(TypeServer2Record &TS); |
| Error traverseTypes(llvm::pdb::PDBFile &Pdb, LazyRandomTypeCollection &Types, |
| LazyRandomTypeCollection &Ids); |
| |
| Error collectInlineeInfo(DebugInlineeLinesSubsectionRef &Lines, |
| const llvm::pdb::SymbolGroup *SG = nullptr); |
| |
| void cacheRelocations(); |
| Error resolveSymbol(const llvm::object::coff_section *CoffSection, |
| uint64_t Offset, llvm::object::SymbolRef &Sym); |
| Error resolveSymbolName(const llvm::object::coff_section *CoffSection, |
| uint64_t Offset, StringRef &Name); |
| Error traverseTypeSection(StringRef SectionName, |
| const llvm::object::SectionRef &Section); |
| Error traverseSymbolSection(StringRef SectionName, |
| const llvm::object::SectionRef &Section); |
| Error traverseInlineeLines(StringRef Subsection); |
| |
| DebugChecksumsSubsectionRef CVFileChecksumTable; |
| DebugStringTableSubsectionRef CVStringTable; |
| |
| Error traverseSymbolsSubsection(StringRef Subsection, |
| const llvm::object::SectionRef &Section, |
| StringRef SectionContents); |
| |
| /// Given a .debug$S section, find the string table and file checksum table. |
| /// This function taken from (COFFDumper.cpp). |
| /// TODO: It can be moved to the COFF library. |
| Error initializeFileAndStringTables(BinaryStreamReader &Reader); |
| |
| Error createLines(const FixedStreamArray<LineNumberEntry> &LineNumbers, |
| LVAddress Addendum, uint32_t Segment, uint32_t Begin, |
| uint32_t Size, uint32_t NameIndex, |
| const llvm::pdb::SymbolGroup *SG = nullptr); |
| Error createScopes(llvm::object::COFFObjectFile &Obj); |
| Error createScopes(llvm::pdb::PDBFile &Pdb); |
| Error processModule(); |
| |
| protected: |
| Error createScopes() override; |
| void sortScopes() override; |
| |
| public: |
| LVCodeViewReader() = delete; |
| LVCodeViewReader(StringRef Filename, StringRef FileFormatName, |
| llvm::object::COFFObjectFile &Obj, ScopedPrinter &W, |
| StringRef ExePath) |
| : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF), |
| Input(&Obj), ExePath(ExePath), LogicalVisitor(this, W, Input) {} |
| LVCodeViewReader(StringRef Filename, StringRef FileFormatName, |
| llvm::pdb::PDBFile &Pdb, ScopedPrinter &W, StringRef ExePath) |
| : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF), |
| Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {} |
| LVCodeViewReader(const LVCodeViewReader &) = delete; |
| LVCodeViewReader &operator=(const LVCodeViewReader &) = delete; |
| ~LVCodeViewReader() = default; |
| |
| void getLinkageName(const llvm::object::coff_section *CoffSection, |
| uint32_t RelocOffset, uint32_t Offset, |
| StringRef *RelocSym); |
| |
| void addModule(LVScope *Scope) { Modules.push_back(Scope); } |
| LVScope *getScopeForModule(uint32_t Modi) { |
| return Modi >= Modules.size() ? nullptr : Modules[Modi]; |
| } |
| |
| // Get the string representation for the CodeView symbols. |
| static StringRef getSymbolKindName(SymbolKind Kind); |
| static std::string formatRegisterId(RegisterId Register, CPUType CPU); |
| |
| std::string getRegisterName(LVSmall Opcode, uint64_t Operands[2]) override; |
| |
| bool isSystemEntry(LVElement *Element, StringRef Name) const override; |
| |
| void print(raw_ostream &OS) const; |
| void printRecords(raw_ostream &OS) const override { |
| LogicalVisitor.printRecords(OS); |
| }; |
| |
| #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
| void dump() const { print(dbgs()); } |
| #endif |
| }; |
| |
| } // end namespace logicalview |
| } // end namespace llvm |
| |
| #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H |