1 //===-- LVCodeViewReader.h --------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the LVCodeViewReader class, which is used to describe a 10 // debug information (COFF) reader. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H 15 #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H 16 17 #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h" 18 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" 19 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 20 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 21 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 22 #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h" 23 #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h" 24 #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 25 #include "llvm/DebugInfo/PDB/PDB.h" 26 #include "llvm/Support/BinaryByteStream.h" 27 #include "llvm/Support/BinaryItemStream.h" 28 #include "llvm/Support/BinaryStreamArray.h" 29 30 namespace llvm { 31 template <> struct BinaryItemTraits<codeview::CVType> { 32 static size_t length(const codeview::CVType &Item) { return Item.length(); } 33 static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) { 34 return Item.data(); 35 } 36 }; 37 38 namespace codeview { 39 class LazyRandomTypeCollection; 40 } 41 namespace object { 42 struct coff_section; 43 } 44 namespace pdb { 45 class SymbolGroup; 46 } 47 namespace logicalview { 48 49 class LVElement; 50 class LVLine; 51 class LVScope; 52 class LVScopeCompileUnit; 53 class LVSymbol; 54 class LVType; 55 class LVTypeVisitor; 56 class LVSymbolVisitor; 57 class LVSymbolVisitorDelegate; 58 59 using LVNames = SmallVector<StringRef, 16>; 60 61 // The ELF reader uses the DWARF constants to create the logical elements. 62 // The DW_TAG_* and DW_AT_* are used to select the logical object and to 63 // set specific attributes, such as name, type, etc. 64 // As the CodeView constants are different to the DWARF constants, the 65 // CodeView reader will map them to the DWARF ones. 66 67 class LVCodeViewReader final : public LVBinaryReader { 68 friend class LVTypeVisitor; 69 friend class LVSymbolVisitor; 70 friend class LVSymbolVisitorDelegate; 71 72 using LVModules = std::vector<LVScope *>; 73 LVModules Modules; 74 75 // Encapsulates access to the input file and any dependent type server, 76 // including any precompiled header object. 77 llvm::pdb::InputFile Input; 78 std::shared_ptr<llvm::pdb::InputFile> TypeServer; 79 std::shared_ptr<LazyRandomTypeCollection> PrecompHeader; 80 81 // Persistance data when loading a type server. 82 ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = nullptr; 83 std::unique_ptr<MemoryBuffer> MemBuffer; 84 std::unique_ptr<llvm::pdb::IPDBSession> Session; 85 std::unique_ptr<llvm::pdb::NativeSession> PdbSession; 86 87 // Persistance data when loading a precompiled header. 88 BumpPtrAllocator BuilderAllocator; 89 std::unique_ptr<AppendingTypeTableBuilder> Builder; 90 std::unique_ptr<BinaryItemStream<CVType>> ItemStream; 91 std::unique_ptr<BinaryStreamReader> ReaderPrecomp; 92 std::vector<CVType> TypeArray; 93 CVTypeArray TypeStream; 94 CVTypeArray CVTypesPrecomp; 95 96 // Persistance data when loading an executable file. 97 std::unique_ptr<MemoryBuffer> BinaryBuffer; 98 std::unique_ptr<llvm::object::Binary> BinaryExecutable; 99 100 Error loadTargetInfo(const object::ObjectFile &Obj); 101 Error loadTargetInfo(const llvm::pdb::PDBFile &Pdb); 102 103 void mapRangeAddress(const object::ObjectFile &Obj, 104 const object::SectionRef &Section, 105 bool IsComdat) override; 106 107 llvm::object::COFFObjectFile &getObj() { return Input.obj(); } 108 llvm::pdb::PDBFile &getPdb() { return Input.pdb(); } 109 bool isObj() const { return Input.isObj(); } 110 bool isPdb() const { return Input.isPdb(); } 111 StringRef getFileName() { return Input.getFilePath(); } 112 113 // Pathname to executable image. 114 std::string ExePath; 115 116 LVOffset CurrentOffset = 0; 117 int32_t CurrentModule = -1; 118 119 using RelocMapTy = DenseMap<const llvm::object::coff_section *, 120 std::vector<llvm::object::RelocationRef>>; 121 RelocMapTy RelocMap; 122 123 // Object files have only one type stream that contains both types and ids. 124 // Precompiled header objects don't contain an IPI stream. Use the TPI. 125 LazyRandomTypeCollection &types() { 126 return TypeServer ? TypeServer->types() 127 : (PrecompHeader ? *PrecompHeader : Input.types()); 128 } 129 LazyRandomTypeCollection &ids() { 130 return TypeServer ? TypeServer->ids() 131 : (PrecompHeader ? *PrecompHeader : Input.ids()); 132 } 133 134 LVLogicalVisitor LogicalVisitor; 135 136 Expected<StringRef> 137 getFileNameForFileOffset(uint32_t FileOffset, 138 const llvm::pdb::SymbolGroup *SG = nullptr); 139 void printRelocatedField(StringRef Label, 140 const llvm::object::coff_section *CoffSection, 141 uint32_t RelocOffset, uint32_t Offset, 142 StringRef *RelocSym); 143 144 Error printFileNameForOffset(StringRef Label, uint32_t FileOffset, 145 const llvm::pdb::SymbolGroup *SG = nullptr); 146 147 Error loadPrecompiledObject(PrecompRecord &Precomp, CVTypeArray &CVTypesObj); 148 Error loadTypeServer(TypeServer2Record &TS); 149 Error traverseTypes(llvm::pdb::PDBFile &Pdb, LazyRandomTypeCollection &Types, 150 LazyRandomTypeCollection &Ids); 151 152 Error collectInlineeInfo(DebugInlineeLinesSubsectionRef &Lines, 153 const llvm::pdb::SymbolGroup *SG = nullptr); 154 155 void cacheRelocations(); 156 Error resolveSymbol(const llvm::object::coff_section *CoffSection, 157 uint64_t Offset, llvm::object::SymbolRef &Sym); 158 Error resolveSymbolName(const llvm::object::coff_section *CoffSection, 159 uint64_t Offset, StringRef &Name); 160 Error traverseTypeSection(StringRef SectionName, 161 const llvm::object::SectionRef &Section); 162 Error traverseSymbolSection(StringRef SectionName, 163 const llvm::object::SectionRef &Section); 164 Error traverseInlineeLines(StringRef Subsection); 165 166 DebugChecksumsSubsectionRef CVFileChecksumTable; 167 DebugStringTableSubsectionRef CVStringTable; 168 169 Error traverseSymbolsSubsection(StringRef Subsection, 170 const llvm::object::SectionRef &Section, 171 StringRef SectionContents); 172 173 /// Given a .debug$S section, find the string table and file checksum table. 174 /// This function taken from (COFFDumper.cpp). 175 /// TODO: It can be moved to the COFF library. 176 Error initializeFileAndStringTables(BinaryStreamReader &Reader); 177 178 Error createLines(const FixedStreamArray<LineNumberEntry> &LineNumbers, 179 LVAddress Addendum, uint32_t Segment, uint32_t Begin, 180 uint32_t Size, uint32_t NameIndex, 181 const llvm::pdb::SymbolGroup *SG = nullptr); 182 Error createScopes(llvm::object::COFFObjectFile &Obj); 183 Error createScopes(llvm::pdb::PDBFile &Pdb); 184 Error processModule(); 185 186 protected: 187 Error createScopes() override; 188 void sortScopes() override; 189 190 public: 191 LVCodeViewReader() = delete; 192 LVCodeViewReader(StringRef Filename, StringRef FileFormatName, 193 llvm::object::COFFObjectFile &Obj, ScopedPrinter &W, 194 StringRef ExePath) 195 : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF), 196 Input(&Obj), ExePath(ExePath), LogicalVisitor(this, W, Input) {} 197 LVCodeViewReader(StringRef Filename, StringRef FileFormatName, 198 llvm::pdb::PDBFile &Pdb, ScopedPrinter &W, StringRef ExePath) 199 : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF), 200 Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {} 201 LVCodeViewReader(const LVCodeViewReader &) = delete; 202 LVCodeViewReader &operator=(const LVCodeViewReader &) = delete; 203 ~LVCodeViewReader() = default; 204 205 void getLinkageName(const llvm::object::coff_section *CoffSection, 206 uint32_t RelocOffset, uint32_t Offset, 207 StringRef *RelocSym); 208 209 void addModule(LVScope *Scope) { Modules.push_back(Scope); } 210 LVScope *getScopeForModule(uint32_t Modi) { 211 return Modi >= Modules.size() ? nullptr : Modules[Modi]; 212 } 213 214 // Get the string representation for the CodeView symbols. 215 static StringRef getSymbolKindName(SymbolKind Kind); 216 static std::string formatRegisterId(RegisterId Register, CPUType CPU); 217 218 std::string getRegisterName(LVSmall Opcode, 219 ArrayRef<uint64_t> Operands) override; 220 221 bool isSystemEntry(LVElement *Element, StringRef Name) const override; 222 223 void print(raw_ostream &OS) const; 224 void printRecords(raw_ostream &OS) const override { 225 LogicalVisitor.printRecords(OS); 226 }; 227 228 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 229 void dump() const { print(dbgs()); } 230 #endif 231 }; 232 233 } // end namespace logicalview 234 } // end namespace llvm 235 236 #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWREADER_H 237