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
30namespace llvm {
31template <> 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
38namespace codeview {
39class LazyRandomTypeCollection;
40}
41namespace object {
42struct coff_section;
43}
44namespace pdb {
45class SymbolGroup;
46}
47namespace logicalview {
48
49class LVElement;
50class LVLine;
51class LVScope;
52class LVScopeCompileUnit;
53class LVSymbol;
54class LVType;
55class LVTypeVisitor;
56class LVSymbolVisitor;
57class LVSymbolVisitorDelegate;
58
59using LVNames = SmallVector<StringRef, 16>;
60
61// The DWARF 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
67class 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
186protected:
187 Error createScopes() override;
188 void sortScopes() override;
189
190public:
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(x: 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