106c3fb27SDimitry Andric //===-- LVCodeViewReader.h --------------------------------------*- C++ -*-===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric // 906c3fb27SDimitry Andric // This file defines the LVCodeViewReader class, which is used to describe a 1006c3fb27SDimitry Andric // debug information (COFF) reader. 1106c3fb27SDimitry Andric // 1206c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1306c3fb27SDimitry Andric 1406c3fb27SDimitry Andric #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H 1506c3fb27SDimitry Andric #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H 1606c3fb27SDimitry Andric 1706c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h" 1806c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" 1906c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 2006c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 2106c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecord.h" 2206c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h" 2306c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h" 2406c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 2506c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h" 2606c3fb27SDimitry Andric #include "llvm/Support/BinaryByteStream.h" 2706c3fb27SDimitry Andric #include "llvm/Support/BinaryItemStream.h" 2806c3fb27SDimitry Andric #include "llvm/Support/BinaryStreamArray.h" 2906c3fb27SDimitry Andric 3006c3fb27SDimitry Andric namespace llvm { 3106c3fb27SDimitry Andric template <> struct BinaryItemTraits<codeview::CVType> { 3206c3fb27SDimitry Andric static size_t length(const codeview::CVType &Item) { return Item.length(); } 3306c3fb27SDimitry Andric static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) { 3406c3fb27SDimitry Andric return Item.data(); 3506c3fb27SDimitry Andric } 3606c3fb27SDimitry Andric }; 3706c3fb27SDimitry Andric 3806c3fb27SDimitry Andric namespace codeview { 3906c3fb27SDimitry Andric class LazyRandomTypeCollection; 4006c3fb27SDimitry Andric } 4106c3fb27SDimitry Andric namespace object { 4206c3fb27SDimitry Andric struct coff_section; 4306c3fb27SDimitry Andric } 4406c3fb27SDimitry Andric namespace pdb { 4506c3fb27SDimitry Andric class SymbolGroup; 4606c3fb27SDimitry Andric } 4706c3fb27SDimitry Andric namespace logicalview { 4806c3fb27SDimitry Andric 4906c3fb27SDimitry Andric class LVElement; 5006c3fb27SDimitry Andric class LVLine; 5106c3fb27SDimitry Andric class LVScope; 5206c3fb27SDimitry Andric class LVScopeCompileUnit; 5306c3fb27SDimitry Andric class LVSymbol; 5406c3fb27SDimitry Andric class LVType; 5506c3fb27SDimitry Andric class LVTypeVisitor; 5606c3fb27SDimitry Andric class LVSymbolVisitor; 5706c3fb27SDimitry Andric class LVSymbolVisitorDelegate; 5806c3fb27SDimitry Andric 5906c3fb27SDimitry Andric using LVNames = SmallVector<StringRef, 16>; 6006c3fb27SDimitry Andric 61*0fca6ea1SDimitry Andric // The DWARF reader uses the DWARF constants to create the logical elements. 6206c3fb27SDimitry Andric // The DW_TAG_* and DW_AT_* are used to select the logical object and to 6306c3fb27SDimitry Andric // set specific attributes, such as name, type, etc. 6406c3fb27SDimitry Andric // As the CodeView constants are different to the DWARF constants, the 6506c3fb27SDimitry Andric // CodeView reader will map them to the DWARF ones. 6606c3fb27SDimitry Andric 6706c3fb27SDimitry Andric class LVCodeViewReader final : public LVBinaryReader { 6806c3fb27SDimitry Andric friend class LVTypeVisitor; 6906c3fb27SDimitry Andric friend class LVSymbolVisitor; 7006c3fb27SDimitry Andric friend class LVSymbolVisitorDelegate; 7106c3fb27SDimitry Andric 7206c3fb27SDimitry Andric using LVModules = std::vector<LVScope *>; 7306c3fb27SDimitry Andric LVModules Modules; 7406c3fb27SDimitry Andric 7506c3fb27SDimitry Andric // Encapsulates access to the input file and any dependent type server, 7606c3fb27SDimitry Andric // including any precompiled header object. 7706c3fb27SDimitry Andric llvm::pdb::InputFile Input; 7806c3fb27SDimitry Andric std::shared_ptr<llvm::pdb::InputFile> TypeServer; 7906c3fb27SDimitry Andric std::shared_ptr<LazyRandomTypeCollection> PrecompHeader; 8006c3fb27SDimitry Andric 8106c3fb27SDimitry Andric // Persistance data when loading a type server. 8206c3fb27SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = nullptr; 8306c3fb27SDimitry Andric std::unique_ptr<MemoryBuffer> MemBuffer; 8406c3fb27SDimitry Andric std::unique_ptr<llvm::pdb::IPDBSession> Session; 8506c3fb27SDimitry Andric std::unique_ptr<llvm::pdb::NativeSession> PdbSession; 8606c3fb27SDimitry Andric 8706c3fb27SDimitry Andric // Persistance data when loading a precompiled header. 8806c3fb27SDimitry Andric BumpPtrAllocator BuilderAllocator; 8906c3fb27SDimitry Andric std::unique_ptr<AppendingTypeTableBuilder> Builder; 9006c3fb27SDimitry Andric std::unique_ptr<BinaryItemStream<CVType>> ItemStream; 9106c3fb27SDimitry Andric std::unique_ptr<BinaryStreamReader> ReaderPrecomp; 9206c3fb27SDimitry Andric std::vector<CVType> TypeArray; 9306c3fb27SDimitry Andric CVTypeArray TypeStream; 9406c3fb27SDimitry Andric CVTypeArray CVTypesPrecomp; 9506c3fb27SDimitry Andric 9606c3fb27SDimitry Andric // Persistance data when loading an executable file. 9706c3fb27SDimitry Andric std::unique_ptr<MemoryBuffer> BinaryBuffer; 9806c3fb27SDimitry Andric std::unique_ptr<llvm::object::Binary> BinaryExecutable; 9906c3fb27SDimitry Andric 10006c3fb27SDimitry Andric Error loadTargetInfo(const object::ObjectFile &Obj); 10106c3fb27SDimitry Andric Error loadTargetInfo(const llvm::pdb::PDBFile &Pdb); 10206c3fb27SDimitry Andric 10306c3fb27SDimitry Andric void mapRangeAddress(const object::ObjectFile &Obj, 10406c3fb27SDimitry Andric const object::SectionRef &Section, 10506c3fb27SDimitry Andric bool IsComdat) override; 10606c3fb27SDimitry Andric 10706c3fb27SDimitry Andric llvm::object::COFFObjectFile &getObj() { return Input.obj(); } 10806c3fb27SDimitry Andric llvm::pdb::PDBFile &getPdb() { return Input.pdb(); } 10906c3fb27SDimitry Andric bool isObj() const { return Input.isObj(); } 11006c3fb27SDimitry Andric bool isPdb() const { return Input.isPdb(); } 11106c3fb27SDimitry Andric StringRef getFileName() { return Input.getFilePath(); } 11206c3fb27SDimitry Andric 11306c3fb27SDimitry Andric // Pathname to executable image. 11406c3fb27SDimitry Andric std::string ExePath; 11506c3fb27SDimitry Andric 11606c3fb27SDimitry Andric LVOffset CurrentOffset = 0; 11706c3fb27SDimitry Andric int32_t CurrentModule = -1; 11806c3fb27SDimitry Andric 11906c3fb27SDimitry Andric using RelocMapTy = DenseMap<const llvm::object::coff_section *, 12006c3fb27SDimitry Andric std::vector<llvm::object::RelocationRef>>; 12106c3fb27SDimitry Andric RelocMapTy RelocMap; 12206c3fb27SDimitry Andric 12306c3fb27SDimitry Andric // Object files have only one type stream that contains both types and ids. 12406c3fb27SDimitry Andric // Precompiled header objects don't contain an IPI stream. Use the TPI. 12506c3fb27SDimitry Andric LazyRandomTypeCollection &types() { 12606c3fb27SDimitry Andric return TypeServer ? TypeServer->types() 12706c3fb27SDimitry Andric : (PrecompHeader ? *PrecompHeader : Input.types()); 12806c3fb27SDimitry Andric } 12906c3fb27SDimitry Andric LazyRandomTypeCollection &ids() { 13006c3fb27SDimitry Andric return TypeServer ? TypeServer->ids() 13106c3fb27SDimitry Andric : (PrecompHeader ? *PrecompHeader : Input.ids()); 13206c3fb27SDimitry Andric } 13306c3fb27SDimitry Andric 13406c3fb27SDimitry Andric LVLogicalVisitor LogicalVisitor; 13506c3fb27SDimitry Andric 13606c3fb27SDimitry Andric Expected<StringRef> 13706c3fb27SDimitry Andric getFileNameForFileOffset(uint32_t FileOffset, 13806c3fb27SDimitry Andric const llvm::pdb::SymbolGroup *SG = nullptr); 13906c3fb27SDimitry Andric void printRelocatedField(StringRef Label, 14006c3fb27SDimitry Andric const llvm::object::coff_section *CoffSection, 14106c3fb27SDimitry Andric uint32_t RelocOffset, uint32_t Offset, 14206c3fb27SDimitry Andric StringRef *RelocSym); 14306c3fb27SDimitry Andric 14406c3fb27SDimitry Andric Error printFileNameForOffset(StringRef Label, uint32_t FileOffset, 14506c3fb27SDimitry Andric const llvm::pdb::SymbolGroup *SG = nullptr); 14606c3fb27SDimitry Andric 14706c3fb27SDimitry Andric Error loadPrecompiledObject(PrecompRecord &Precomp, CVTypeArray &CVTypesObj); 14806c3fb27SDimitry Andric Error loadTypeServer(TypeServer2Record &TS); 14906c3fb27SDimitry Andric Error traverseTypes(llvm::pdb::PDBFile &Pdb, LazyRandomTypeCollection &Types, 15006c3fb27SDimitry Andric LazyRandomTypeCollection &Ids); 15106c3fb27SDimitry Andric 15206c3fb27SDimitry Andric Error collectInlineeInfo(DebugInlineeLinesSubsectionRef &Lines, 15306c3fb27SDimitry Andric const llvm::pdb::SymbolGroup *SG = nullptr); 15406c3fb27SDimitry Andric 15506c3fb27SDimitry Andric void cacheRelocations(); 15606c3fb27SDimitry Andric Error resolveSymbol(const llvm::object::coff_section *CoffSection, 15706c3fb27SDimitry Andric uint64_t Offset, llvm::object::SymbolRef &Sym); 15806c3fb27SDimitry Andric Error resolveSymbolName(const llvm::object::coff_section *CoffSection, 15906c3fb27SDimitry Andric uint64_t Offset, StringRef &Name); 16006c3fb27SDimitry Andric Error traverseTypeSection(StringRef SectionName, 16106c3fb27SDimitry Andric const llvm::object::SectionRef &Section); 16206c3fb27SDimitry Andric Error traverseSymbolSection(StringRef SectionName, 16306c3fb27SDimitry Andric const llvm::object::SectionRef &Section); 16406c3fb27SDimitry Andric Error traverseInlineeLines(StringRef Subsection); 16506c3fb27SDimitry Andric 16606c3fb27SDimitry Andric DebugChecksumsSubsectionRef CVFileChecksumTable; 16706c3fb27SDimitry Andric DebugStringTableSubsectionRef CVStringTable; 16806c3fb27SDimitry Andric 16906c3fb27SDimitry Andric Error traverseSymbolsSubsection(StringRef Subsection, 17006c3fb27SDimitry Andric const llvm::object::SectionRef &Section, 17106c3fb27SDimitry Andric StringRef SectionContents); 17206c3fb27SDimitry Andric 17306c3fb27SDimitry Andric /// Given a .debug$S section, find the string table and file checksum table. 17406c3fb27SDimitry Andric /// This function taken from (COFFDumper.cpp). 17506c3fb27SDimitry Andric /// TODO: It can be moved to the COFF library. 17606c3fb27SDimitry Andric Error initializeFileAndStringTables(BinaryStreamReader &Reader); 17706c3fb27SDimitry Andric 17806c3fb27SDimitry Andric Error createLines(const FixedStreamArray<LineNumberEntry> &LineNumbers, 17906c3fb27SDimitry Andric LVAddress Addendum, uint32_t Segment, uint32_t Begin, 18006c3fb27SDimitry Andric uint32_t Size, uint32_t NameIndex, 18106c3fb27SDimitry Andric const llvm::pdb::SymbolGroup *SG = nullptr); 18206c3fb27SDimitry Andric Error createScopes(llvm::object::COFFObjectFile &Obj); 18306c3fb27SDimitry Andric Error createScopes(llvm::pdb::PDBFile &Pdb); 18406c3fb27SDimitry Andric Error processModule(); 18506c3fb27SDimitry Andric 18606c3fb27SDimitry Andric protected: 18706c3fb27SDimitry Andric Error createScopes() override; 18806c3fb27SDimitry Andric void sortScopes() override; 18906c3fb27SDimitry Andric 19006c3fb27SDimitry Andric public: 19106c3fb27SDimitry Andric LVCodeViewReader() = delete; 19206c3fb27SDimitry Andric LVCodeViewReader(StringRef Filename, StringRef FileFormatName, 19306c3fb27SDimitry Andric llvm::object::COFFObjectFile &Obj, ScopedPrinter &W, 19406c3fb27SDimitry Andric StringRef ExePath) 19506c3fb27SDimitry Andric : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF), 19606c3fb27SDimitry Andric Input(&Obj), ExePath(ExePath), LogicalVisitor(this, W, Input) {} 19706c3fb27SDimitry Andric LVCodeViewReader(StringRef Filename, StringRef FileFormatName, 19806c3fb27SDimitry Andric llvm::pdb::PDBFile &Pdb, ScopedPrinter &W, StringRef ExePath) 19906c3fb27SDimitry Andric : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF), 20006c3fb27SDimitry Andric Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {} 20106c3fb27SDimitry Andric LVCodeViewReader(const LVCodeViewReader &) = delete; 20206c3fb27SDimitry Andric LVCodeViewReader &operator=(const LVCodeViewReader &) = delete; 20306c3fb27SDimitry Andric ~LVCodeViewReader() = default; 20406c3fb27SDimitry Andric 20506c3fb27SDimitry Andric void getLinkageName(const llvm::object::coff_section *CoffSection, 20606c3fb27SDimitry Andric uint32_t RelocOffset, uint32_t Offset, 20706c3fb27SDimitry Andric StringRef *RelocSym); 20806c3fb27SDimitry Andric 20906c3fb27SDimitry Andric void addModule(LVScope *Scope) { Modules.push_back(Scope); } 21006c3fb27SDimitry Andric LVScope *getScopeForModule(uint32_t Modi) { 21106c3fb27SDimitry Andric return Modi >= Modules.size() ? nullptr : Modules[Modi]; 21206c3fb27SDimitry Andric } 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric // Get the string representation for the CodeView symbols. 21506c3fb27SDimitry Andric static StringRef getSymbolKindName(SymbolKind Kind); 21606c3fb27SDimitry Andric static std::string formatRegisterId(RegisterId Register, CPUType CPU); 21706c3fb27SDimitry Andric 21806c3fb27SDimitry Andric std::string getRegisterName(LVSmall Opcode, 21906c3fb27SDimitry Andric ArrayRef<uint64_t> Operands) override; 22006c3fb27SDimitry Andric 22106c3fb27SDimitry Andric bool isSystemEntry(LVElement *Element, StringRef Name) const override; 22206c3fb27SDimitry Andric 22306c3fb27SDimitry Andric void print(raw_ostream &OS) const; 22406c3fb27SDimitry Andric void printRecords(raw_ostream &OS) const override { 22506c3fb27SDimitry Andric LogicalVisitor.printRecords(OS); 22606c3fb27SDimitry Andric }; 22706c3fb27SDimitry Andric 22806c3fb27SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 22906c3fb27SDimitry Andric void dump() const { print(dbgs()); } 23006c3fb27SDimitry Andric #endif 23106c3fb27SDimitry Andric }; 23206c3fb27SDimitry Andric 23306c3fb27SDimitry Andric } // end namespace logicalview 23406c3fb27SDimitry Andric } // end namespace llvm 23506c3fb27SDimitry Andric 23606c3fb27SDimitry Andric #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H 237