1//===-- LVCodeViewVisitor.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 LVCodeViewVisitor class, which is used to describe a
10// debug information (CodeView) visitor.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H
15#define LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H
16
17#include "llvm/ADT/iterator.h"
18#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
19#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
20#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
21#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
22#include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h"
23#include "llvm/DebugInfo/PDB/Native/InputFile.h"
24#include "llvm/Object/Binary.h"
25#include "llvm/Object/ObjectFile.h"
26#include "llvm/Support/Error.h"
27#include <stack>
28#include <utility>
29
30namespace llvm {
31namespace logicalview {
32
33using namespace llvm::codeview;
34
35class LVCodeViewReader;
36class LVLogicalVisitor;
37struct LVShared;
38
39class LVTypeVisitor final : public TypeVisitorCallbacks {
40 ScopedPrinter &W;
41 LVLogicalVisitor *LogicalVisitor;
42 LazyRandomTypeCollection &Types;
43 LazyRandomTypeCollection &Ids;
44 uint32_t StreamIdx;
45 LVShared *Shared = nullptr;
46
47 // In a PDB, a type index may refer to a type (TPI) or an item ID (IPI).
48 // In a COFF or PDB (/Z7), the type index always refer to a type (TPI).
49 // When creating logical elements, we must access the correct element
50 // table, while searching for a type index.
51 bool HasIds = false;
52
53 // Current type index during the types traversal.
54 TypeIndex CurrentTypeIndex = TypeIndex::None();
55
56 void printTypeIndex(StringRef FieldName, TypeIndex TI,
57 uint32_t StreamIdx) const;
58
59public:
60 LVTypeVisitor(ScopedPrinter &W, LVLogicalVisitor *LogicalVisitor,
61 LazyRandomTypeCollection &Types, LazyRandomTypeCollection &Ids,
62 uint32_t StreamIdx, LVShared *Shared)
63 : TypeVisitorCallbacks(), W(W), LogicalVisitor(LogicalVisitor),
64 Types(Types), Ids(Ids), StreamIdx(StreamIdx), Shared(Shared) {
65 HasIds = &Types != &Ids;
66 }
67
68 Error visitTypeBegin(CVType &Record) override;
69 Error visitTypeBegin(CVType &Record, TypeIndex TI) override;
70 Error visitMemberBegin(CVMemberRecord &Record) override;
71 Error visitMemberEnd(CVMemberRecord &Record) override;
72 Error visitUnknownMember(CVMemberRecord &Record) override;
73
74 Error visitKnownRecord(CVType &Record, BuildInfoRecord &Args) override;
75 Error visitKnownRecord(CVType &Record, ClassRecord &Class) override;
76 Error visitKnownRecord(CVType &Record, EnumRecord &Enum) override;
77 Error visitKnownRecord(CVType &Record, FuncIdRecord &Func) override;
78 Error visitKnownRecord(CVType &Record, ProcedureRecord &Proc) override;
79 Error visitKnownRecord(CVType &Record, StringIdRecord &String) override;
80 Error visitKnownRecord(CVType &Record, UdtSourceLineRecord &Line) override;
81 Error visitKnownRecord(CVType &Record, UnionRecord &Union) override;
82 Error visitUnknownType(CVType &Record) override;
83};
84
85class LVSymbolVisitorDelegate final : public SymbolVisitorDelegate {
86 LVCodeViewReader *Reader;
87 const llvm::object::coff_section *CoffSection;
88 StringRef SectionContents;
89
90public:
91 LVSymbolVisitorDelegate(LVCodeViewReader *Reader,
92 const llvm::object::SectionRef &Section,
93 const llvm::object::COFFObjectFile *Obj,
94 StringRef SectionContents)
95 : Reader(Reader), SectionContents(SectionContents) {
96 CoffSection = Obj->getCOFFSection(Section);
97 }
98
99 uint32_t getRecordOffset(BinaryStreamReader Reader) override {
100 ArrayRef<uint8_t> Data;
101 if (Error Err = Reader.readLongestContiguousChunk(Buffer&: Data)) {
102 llvm::consumeError(Err: std::move(Err));
103 return 0;
104 }
105 return Data.data() - SectionContents.bytes_begin();
106 }
107
108 void printRelocatedField(StringRef Label, uint32_t RelocOffset,
109 uint32_t Offset, StringRef *RelocSym = nullptr);
110
111 void getLinkageName(uint32_t RelocOffset, uint32_t Offset,
112 StringRef *RelocSym = nullptr);
113
114 StringRef getFileNameForFileOffset(uint32_t FileOffset) override;
115 DebugStringTableSubsectionRef getStringTable() override;
116};
117
118class LVElement;
119class LVScope;
120class LVSymbol;
121class LVType;
122
123// Visitor for CodeView symbol streams found in COFF object files and PDB files.
124class LVSymbolVisitor final : public SymbolVisitorCallbacks {
125 LVCodeViewReader *Reader;
126 ScopedPrinter &W;
127 LVLogicalVisitor *LogicalVisitor;
128 LazyRandomTypeCollection &Types;
129 LazyRandomTypeCollection &Ids;
130 LVSymbolVisitorDelegate *ObjDelegate;
131 LVShared *Shared;
132
133 // Symbol offset when processing PDB streams.
134 uint32_t CurrentOffset = 0;
135 // Current object name collected from S_OBJNAME.
136 StringRef CurrentObjectName;
137 // Last symbol processed by S_LOCAL.
138 LVSymbol *LocalSymbol = nullptr;
139
140 bool HasIds;
141 bool InFunctionScope = false;
142 bool IsCompileUnit = false;
143
144 // Register for the locals and parameters symbols in the current frame.
145 RegisterId LocalFrameRegister = RegisterId::NONE;
146 RegisterId ParamFrameRegister = RegisterId::NONE;
147
148 void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
149 uint32_t RelocationOffset);
150 void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
151 void printTypeIndex(StringRef FieldName, TypeIndex TI) const;
152
153 // Return true if this symbol is a Compile Unit.
154 bool symbolIsCompileUnit(SymbolKind Kind) {
155 switch (Kind) {
156 case SymbolKind::S_COMPILE2:
157 case SymbolKind::S_COMPILE3:
158 return true;
159 default:
160 return false;
161 }
162 }
163
164 // Determine symbol kind (local or parameter).
165 void determineSymbolKind(LVSymbol *Symbol, RegisterId Register) {
166 if (Register == LocalFrameRegister) {
167 Symbol->setIsVariable();
168 return;
169 }
170 if (Register == ParamFrameRegister) {
171 Symbol->setIsParameter();
172 return;
173 }
174 // Assume is a variable.
175 Symbol->setIsVariable();
176 }
177
178public:
179 LVSymbolVisitor(LVCodeViewReader *Reader, ScopedPrinter &W,
180 LVLogicalVisitor *LogicalVisitor,
181 LazyRandomTypeCollection &Types,
182 LazyRandomTypeCollection &Ids,
183 LVSymbolVisitorDelegate *ObjDelegate, LVShared *Shared)
184 : Reader(Reader), W(W), LogicalVisitor(LogicalVisitor), Types(Types),
185 Ids(Ids), ObjDelegate(ObjDelegate), Shared(Shared) {
186 HasIds = &Types != &Ids;
187 }
188
189 Error visitSymbolBegin(CVSymbol &Record) override;
190 Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override;
191 Error visitSymbolEnd(CVSymbol &Record) override;
192 Error visitUnknownSymbol(CVSymbol &Record) override;
193
194 Error visitKnownRecord(CVSymbol &Record, BlockSym &Block) override;
195 Error visitKnownRecord(CVSymbol &Record, BPRelativeSym &Local) override;
196 Error visitKnownRecord(CVSymbol &Record, BuildInfoSym &BuildInfo) override;
197 Error visitKnownRecord(CVSymbol &Record, Compile2Sym &Compile2) override;
198 Error visitKnownRecord(CVSymbol &Record, Compile3Sym &Compile3) override;
199 Error visitKnownRecord(CVSymbol &Record, ConstantSym &Constant) override;
200 Error visitKnownRecord(CVSymbol &Record, DataSym &Data) override;
201 Error visitKnownRecord(CVSymbol &Record,
202 DefRangeFramePointerRelFullScopeSym
203 &DefRangeFramePointerRelFullScope) override;
204 Error visitKnownRecord(
205 CVSymbol &Record,
206 DefRangeFramePointerRelSym &DefRangeFramePointerRel) override;
207 Error visitKnownRecord(CVSymbol &Record,
208 DefRangeRegisterRelSym &DefRangeRegisterRel) override;
209 Error visitKnownRecord(CVSymbol &Record,
210 DefRangeRegisterSym &DefRangeRegister) override;
211 Error visitKnownRecord(
212 CVSymbol &Record,
213 DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) override;
214 Error visitKnownRecord(CVSymbol &Record,
215 DefRangeSubfieldSym &DefRangeSubfield) override;
216 Error visitKnownRecord(CVSymbol &Record, DefRangeSym &DefRange) override;
217 Error visitKnownRecord(CVSymbol &Record, FrameProcSym &FrameProc) override;
218 Error visitKnownRecord(CVSymbol &Record, InlineSiteSym &InlineSite) override;
219 Error visitKnownRecord(CVSymbol &Record, LocalSym &Local) override;
220 Error visitKnownRecord(CVSymbol &Record, ObjNameSym &ObjName) override;
221 Error visitKnownRecord(CVSymbol &Record, ProcSym &Proc) override;
222 Error visitKnownRecord(CVSymbol &Record, RegRelativeSym &Local) override;
223 Error visitKnownRecord(CVSymbol &Record, ScopeEndSym &ScopeEnd) override;
224 Error visitKnownRecord(CVSymbol &Record, Thunk32Sym &Thunk) override;
225 Error visitKnownRecord(CVSymbol &Record, UDTSym &UDT) override;
226 Error visitKnownRecord(CVSymbol &Record, UsingNamespaceSym &UN) override;
227 Error visitKnownRecord(CVSymbol &Record, JumpTableSym &JumpTable) override;
228 Error visitKnownRecord(CVSymbol &Record, CallerSym &Caller) override;
229};
230
231// Visitor for CodeView types and symbols to populate elements.
232class LVLogicalVisitor final {
233 LVCodeViewReader *Reader;
234 ScopedPrinter &W;
235
236 // Encapsulates access to the input file and any dependent type server,
237 // including any precompiled header object.
238 llvm::pdb::InputFile &Input;
239 std::shared_ptr<llvm::pdb::InputFile> TypeServer = nullptr;
240 std::shared_ptr<LazyRandomTypeCollection> PrecompHeader = nullptr;
241
242 std::shared_ptr<LVShared> Shared;
243
244 // Object files have only one type stream that contains both types and ids.
245 // Precompiled header objects don't contain an IPI stream. Use the TPI.
246 LazyRandomTypeCollection &types() {
247 return TypeServer ? TypeServer->types()
248 : (PrecompHeader ? *PrecompHeader : Input.types());
249 }
250 LazyRandomTypeCollection &ids() {
251 return TypeServer ? TypeServer->ids()
252 : (PrecompHeader ? *PrecompHeader : Input.ids());
253 }
254
255 using LVScopeStack = std::stack<LVScope *>;
256 LVScopeStack ScopeStack;
257 LVScope *ReaderParent = nullptr;
258 LVScope *ReaderScope = nullptr;
259 bool InCompileUnitScope = false;
260
261 // Allow processing of argument list.
262 bool ProcessArgumentList = false;
263 StringRef OverloadedMethodName;
264 std::string CompileUnitName;
265
266 // Inlined functions source information.
267 using LVInlineeEntry = std::pair<uint32_t, StringRef>;
268 using LVInlineeInfo = std::map<TypeIndex, LVInlineeEntry>;
269 LVInlineeInfo InlineeInfo;
270
271 Error visitFieldListMemberStream(TypeIndex TI, LVElement *Element,
272 ArrayRef<uint8_t> FieldList);
273
274 LVType *createBaseType(TypeIndex TI, StringRef TypeName);
275 LVType *createPointerType(TypeIndex TI, StringRef TypeName);
276 LVSymbol *createParameter(TypeIndex TI, StringRef Name, LVScope *Parent);
277 LVSymbol *createParameter(LVElement *Element, StringRef Name,
278 LVScope *Parent);
279 void createDataMember(CVMemberRecord &Record, LVScope *Parent, StringRef Name,
280 TypeIndex Type, MemberAccess Access);
281 void createParents(StringRef ScopedName, LVElement *Element);
282
283public:
284 LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W,
285 llvm::pdb::InputFile &Input);
286
287 // Current elements during the processing of a RecordType or RecordSymbol.
288 // They are shared with the SymbolVisitor.
289 LVElement *CurrentElement = nullptr;
290 LVScope *CurrentScope = nullptr;
291 LVSymbol *CurrentSymbol = nullptr;
292 LVType *CurrentType = nullptr;
293
294 // Input source in the case of type server or precompiled header.
295 void setInput(std::shared_ptr<llvm::pdb::InputFile> TypeServer) {
296 this->TypeServer = TypeServer;
297 }
298 void setInput(std::shared_ptr<LazyRandomTypeCollection> PrecompHeader) {
299 this->PrecompHeader = PrecompHeader;
300 }
301
302 void addInlineeInfo(TypeIndex TI, uint32_t LineNumber, StringRef Filename) {
303 InlineeInfo.emplace(args: std::piecewise_construct, args: std::forward_as_tuple(args&: TI),
304 args: std::forward_as_tuple(args&: LineNumber, args&: Filename));
305 }
306
307 void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx);
308 void printMemberAttributes(MemberAttributes Attrs);
309 void printMemberAttributes(MemberAccess Access, MethodKind Kind,
310 MethodOptions Options);
311
312 LVElement *createElement(TypeLeafKind Kind);
313 LVElement *createElement(SymbolKind Kind);
314 LVElement *createElement(TypeIndex TI, TypeLeafKind Kind);
315
316 // Break down the annotation byte code and calculate code and line offsets.
317 Error inlineSiteAnnotation(LVScope *AbstractFunction,
318 LVScope *InlinedFunction,
319 InlineSiteSym &InlineSite);
320
321 void pushScope(LVScope *Scope) {
322 ScopeStack.push(x: ReaderParent);
323 ReaderParent = ReaderScope;
324 ReaderScope = Scope;
325 }
326 void popScope() {
327 ReaderScope = ReaderParent;
328 ReaderParent = ScopeStack.top();
329 ScopeStack.pop();
330 }
331 void closeScope() {
332 if (InCompileUnitScope) {
333 InCompileUnitScope = false;
334 popScope();
335 }
336 }
337 void setRoot(LVScope *Root) { ReaderScope = Root; }
338
339 void addElement(LVScope *Scope, bool IsCompileUnit);
340 void addElement(LVSymbol *Symbol);
341 void addElement(LVType *Type);
342
343 std::string getCompileUnitName() { return CompileUnitName; }
344 void setCompileUnitName(std::string Name) {
345 CompileUnitName = std::move(Name);
346 }
347
348 LVElement *getElement(uint32_t StreamIdx, TypeIndex TI,
349 LVScope *Parent = nullptr);
350 LVShared *getShared() { return Shared.get(); }
351
352 LVScope *getReaderScope() const { return ReaderScope; }
353
354 void printTypeBegin(CVType &Record, TypeIndex TI, LVElement *Element,
355 uint32_t StreamIdx);
356 void printTypeEnd(CVType &Record);
357 void printMemberBegin(CVMemberRecord &Record, TypeIndex TI,
358 LVElement *Element, uint32_t StreamIdx);
359 void printMemberEnd(CVMemberRecord &Record);
360
361 void startProcessArgumentList() { ProcessArgumentList = true; }
362 void stopProcessArgumentList() { ProcessArgumentList = false; }
363
364 void processFiles();
365 void processLines();
366 void processNamespaces();
367
368 void printRecords(raw_ostream &OS) const;
369
370 Error visitUnknownType(CVType &Record, TypeIndex TI);
371 Error visitKnownRecord(CVType &Record, ArgListRecord &Args, TypeIndex TI,
372 LVElement *Element);
373 Error visitKnownRecord(CVType &Record, ArrayRecord &AT, TypeIndex TI,
374 LVElement *Element);
375 Error visitKnownRecord(CVType &Record, BitFieldRecord &BF, TypeIndex TI,
376 LVElement *Element);
377 Error visitKnownRecord(CVType &Record, BuildInfoRecord &BI, TypeIndex TI,
378 LVElement *Element);
379 Error visitKnownRecord(CVType &Record, ClassRecord &Class, TypeIndex TI,
380 LVElement *Element);
381 Error visitKnownRecord(CVType &Record, EnumRecord &Enum, TypeIndex TI,
382 LVElement *Element);
383 Error visitKnownRecord(CVType &Record, FieldListRecord &FieldList,
384 TypeIndex TI, LVElement *Element);
385 Error visitKnownRecord(CVType &Record, FuncIdRecord &Func, TypeIndex TI,
386 LVElement *Element);
387 Error visitKnownRecord(CVType &Record, LabelRecord &LR, TypeIndex TI,
388 LVElement *Element);
389 Error visitKnownRecord(CVType &Record, ModifierRecord &Mod, TypeIndex TI,
390 LVElement *Element);
391 Error visitKnownRecord(CVType &Record, MemberFuncIdRecord &Id, TypeIndex TI,
392 LVElement *Element);
393 Error visitKnownRecord(CVType &Record, MemberFunctionRecord &MF, TypeIndex TI,
394 LVElement *Element);
395 Error visitKnownRecord(CVType &Record, MethodOverloadListRecord &Overloads,
396 TypeIndex TI, LVElement *Element);
397 Error visitKnownRecord(CVType &Record, PointerRecord &Ptr, TypeIndex TI,
398 LVElement *Element);
399 Error visitKnownRecord(CVType &Record, ProcedureRecord &Proc, TypeIndex TI,
400 LVElement *Element);
401 Error visitKnownRecord(CVType &Record, UnionRecord &Union, TypeIndex TI,
402 LVElement *Element);
403 Error visitKnownRecord(CVType &Record, TypeServer2Record &TS, TypeIndex TI,
404 LVElement *Element);
405 Error visitKnownRecord(CVType &Record, VFTableRecord &VFT, TypeIndex TI,
406 LVElement *Element);
407 Error visitKnownRecord(CVType &Record, VFTableShapeRecord &Shape,
408 TypeIndex TI, LVElement *Element);
409 Error visitKnownRecord(CVType &Record, StringListRecord &Strings,
410 TypeIndex TI, LVElement *Element);
411 Error visitKnownRecord(CVType &Record, StringIdRecord &String, TypeIndex TI,
412 LVElement *Element);
413 Error visitKnownRecord(CVType &Record, UdtSourceLineRecord &SourceLine,
414 TypeIndex TI, LVElement *Element);
415 Error visitKnownRecord(CVType &Record, UdtModSourceLineRecord &ModSourceLine,
416 TypeIndex TI, LVElement *Element);
417 Error visitKnownRecord(CVType &Record, PrecompRecord &Precomp, TypeIndex TI,
418 LVElement *Element);
419 Error visitKnownRecord(CVType &Record, EndPrecompRecord &EndPrecomp,
420 TypeIndex TI, LVElement *Element);
421
422 Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI);
423 Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base,
424 TypeIndex TI, LVElement *Element);
425 Error visitKnownMember(CVMemberRecord &Record, DataMemberRecord &Field,
426 TypeIndex TI, LVElement *Element);
427 Error visitKnownMember(CVMemberRecord &Record, EnumeratorRecord &Enum,
428 TypeIndex TI, LVElement *Element);
429 Error visitKnownMember(CVMemberRecord &Record, ListContinuationRecord &Cont,
430 TypeIndex TI, LVElement *Element);
431 Error visitKnownMember(CVMemberRecord &Record, NestedTypeRecord &Nested,
432 TypeIndex TI, LVElement *Element);
433 Error visitKnownMember(CVMemberRecord &Record, OneMethodRecord &Method,
434 TypeIndex TI, LVElement *Element);
435 Error visitKnownMember(CVMemberRecord &Record, OverloadedMethodRecord &Method,
436 TypeIndex TI, LVElement *Element);
437 Error visitKnownMember(CVMemberRecord &Record, StaticDataMemberRecord &Field,
438 TypeIndex TI, LVElement *Element);
439 Error visitKnownMember(CVMemberRecord &Record, VFPtrRecord &VFTable,
440 TypeIndex TI, LVElement *Element);
441 Error visitKnownMember(CVMemberRecord &Record, VirtualBaseClassRecord &Base,
442 TypeIndex TI, LVElement *Element);
443
444 template <typename T>
445 Error visitKnownMember(CVMemberRecord &Record,
446 TypeVisitorCallbacks &Callbacks, TypeIndex TI,
447 LVElement *Element) {
448 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
449 T KnownRecord(RK);
450 if (Error Err = Callbacks.visitKnownMember(Record, KnownRecord))
451 return Err;
452 if (Error Err = visitKnownMember(Record, KnownRecord, TI, Element))
453 return Err;
454 return Error::success();
455 }
456
457 template <typename T>
458 Error visitKnownRecord(CVType &Record, TypeIndex TI, LVElement *Element) {
459 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.kind());
460 T KnownRecord(RK);
461 if (Error Err = TypeDeserializer::deserializeAs(
462 const_cast<CVType &>(Record), KnownRecord))
463 return Err;
464 if (Error Err = visitKnownRecord(Record, KnownRecord, TI, Element))
465 return Err;
466 return Error::success();
467 }
468
469 Error visitMemberRecord(CVMemberRecord &Record,
470 TypeVisitorCallbacks &Callbacks, TypeIndex TI,
471 LVElement *Element);
472 Error finishVisitation(CVType &Record, TypeIndex TI, LVElement *Element);
473};
474
475} // namespace logicalview
476} // namespace llvm
477
478#endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H
479

source code of llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h