LLVM 23.0.0git
LVCodeViewVisitor.h
Go to the documentation of this file.
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"
24#include "llvm/Object/Binary.h"
26#include "llvm/Support/Error.h"
27#include <stack>
28#include <utility>
29
30namespace llvm {
31namespace logicalview {
32
33using namespace llvm::codeview;
34
37struct LVShared;
38
41 LVLogicalVisitor *LogicalVisitor;
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:
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
82 Error visitUnknownType(CVType &Record) override;
83};
84
86 LVCodeViewReader *Reader;
87 const llvm::object::coff_section *CoffSection;
88 StringRef SectionContents;
89
90public:
92 const llvm::object::SectionRef &Section,
94 StringRef SectionContents)
95 : Reader(Reader), SectionContents(SectionContents) {
96 CoffSection = Obj->getCOFFSection(Section);
97 }
98
101 if (Error Err = Reader.readLongestContiguousChunk(Data)) {
102 llvm::consumeError(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.
125 LVCodeViewReader *Reader;
126 ScopedPrinter &W;
127 LVLogicalVisitor *LogicalVisitor;
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
178 void setLocalVariableType(LVSymbol *Symbol, TypeIndex TI);
179
180public:
182 LVLogicalVisitor *LogicalVisitor,
185 LVSymbolVisitorDelegate *ObjDelegate, LVShared *Shared)
186 : Reader(Reader), W(W), LogicalVisitor(LogicalVisitor), Types(Types),
187 Ids(Ids), ObjDelegate(ObjDelegate), Shared(Shared) {
188 HasIds = &Types != &Ids;
189 }
190
191 Error visitSymbolBegin(CVSymbol &Record) override;
192 Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override;
193 Error visitSymbolEnd(CVSymbol &Record) override;
194 Error visitUnknownSymbol(CVSymbol &Record) override;
195
198 Error visitKnownRecord(CVSymbol &Record, BuildInfoSym &BuildInfo) override;
199 Error visitKnownRecord(CVSymbol &Record, Compile2Sym &Compile2) override;
200 Error visitKnownRecord(CVSymbol &Record, Compile3Sym &Compile3) override;
205 &DefRangeFramePointerRelFullScope) override;
208 DefRangeFramePointerRelSym &DefRangeFramePointerRel) override;
210 DefRangeRegisterRelSym &DefRangeRegisterRel) override;
213 DefRangeRegisterRelIndirSym &DefRangeRegisterRelIndir) override;
215 DefRangeRegisterSym &DefRangeRegister) override;
218 DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) override;
220 DefRangeSubfieldSym &DefRangeSubfield) override;
221 Error visitKnownRecord(CVSymbol &Record, DefRangeSym &DefRange) override;
222 Error visitKnownRecord(CVSymbol &Record, FrameProcSym &FrameProc) override;
225 Error visitKnownRecord(CVSymbol &Record, ObjNameSym &ObjName) override;
226 Error visitKnownRecord(CVSymbol &Record, ProcSym &Proc) override;
229 Error visitKnownRecord(CVSymbol &Record, ScopeEndSym &ScopeEnd) override;
234 Error visitKnownRecord(CVSymbol &Record, CallerSym &Caller) override;
235};
236
237// Visitor for CodeView types and symbols to populate elements.
238class LVLogicalVisitor final {
239 LVCodeViewReader *Reader;
240 ScopedPrinter &W;
241
242 // Encapsulates access to the input file and any dependent type server,
243 // including any precompiled header object.
245 std::shared_ptr<llvm::pdb::InputFile> TypeServer = nullptr;
246 std::shared_ptr<LazyRandomTypeCollection> PrecompHeader = nullptr;
247
248 std::shared_ptr<LVShared> Shared;
249
250 // Object files have only one type stream that contains both types and ids.
251 // Precompiled header objects don't contain an IPI stream. Use the TPI.
252 LazyRandomTypeCollection &types() {
253 return TypeServer ? TypeServer->types()
254 : (PrecompHeader ? *PrecompHeader : Input.types());
255 }
257 return TypeServer ? TypeServer->ids()
258 : (PrecompHeader ? *PrecompHeader : Input.ids());
259 }
260
261 using LVScopeStack = std::stack<LVScope *>;
262 LVScopeStack ScopeStack;
263 LVScope *ReaderParent = nullptr;
264 LVScope *ReaderScope = nullptr;
265 bool InCompileUnitScope = false;
266
267 // Allow processing of argument list.
268 bool ProcessArgumentList = false;
269 StringRef OverloadedMethodName;
270 std::string CompileUnitName;
271
272 // Inlined functions source information.
273 using LVInlineeEntry = std::pair<uint32_t, StringRef>;
274 using LVInlineeInfo = std::map<TypeIndex, LVInlineeEntry>;
275 LVInlineeInfo InlineeInfo;
276
277 Error visitFieldListMemberStream(TypeIndex TI, LVElement *Element,
279
280 LVType *createBaseType(TypeIndex TI, StringRef TypeName);
281 LVType *createPointerType(TypeIndex TI, StringRef TypeName);
282 LVSymbol *createParameter(TypeIndex TI, StringRef Name, LVScope *Parent);
283 LVSymbol *createParameter(LVElement *Element, StringRef Name,
284 LVScope *Parent);
285 void createDataMember(CVMemberRecord &Record, LVScope *Parent, StringRef Name,
287 void createParents(StringRef ScopedName, LVElement *Element);
288
289public:
291 llvm::pdb::InputFile &Input);
292
293 // Current elements during the processing of a RecordType or RecordSymbol.
294 // They are shared with the SymbolVisitor.
298 LVType *CurrentType = nullptr;
299
300 // Input source in the case of type server or precompiled header.
301 void setInput(std::shared_ptr<llvm::pdb::InputFile> TypeServer) {
302 this->TypeServer = TypeServer;
303 }
304 void setInput(std::shared_ptr<LazyRandomTypeCollection> PrecompHeader) {
305 this->PrecompHeader = PrecompHeader;
306 }
307
309 InlineeInfo.emplace(std::piecewise_construct, std::forward_as_tuple(TI),
310 std::forward_as_tuple(LineNumber, Filename));
311 }
312
313 LLVM_ABI void printTypeIndex(StringRef FieldName, TypeIndex TI,
314 uint32_t StreamIdx);
318
322
323 // Break down the annotation byte code and calculate code and line offsets.
324 LLVM_ABI Error inlineSiteAnnotation(LVScope *AbstractFunction,
325 LVScope *InlinedFunction,
327
328 void pushScope(LVScope *Scope) {
329 ScopeStack.push(ReaderParent);
330 ReaderParent = ReaderScope;
331 ReaderScope = Scope;
332 }
333 void popScope() {
334 ReaderScope = ReaderParent;
335 ReaderParent = ScopeStack.top();
336 ScopeStack.pop();
337 }
338 void closeScope() {
339 if (InCompileUnitScope) {
340 InCompileUnitScope = false;
341 popScope();
342 }
343 }
344 void setRoot(LVScope *Root) { ReaderScope = Root; }
345
346 LLVM_ABI void addElement(LVScope *Scope, bool IsCompileUnit);
347 LLVM_ABI void addElement(LVSymbol *Symbol);
349
350 std::string getCompileUnitName() { return CompileUnitName; }
351 void setCompileUnitName(std::string Name) {
352 CompileUnitName = std::move(Name);
353 }
354
356 LVScope *Parent = nullptr);
357 LVShared *getShared() { return Shared.get(); }
358
359 LVScope *getReaderScope() const { return ReaderScope; }
360
362 uint32_t StreamIdx);
365 LVElement *Element, uint32_t StreamIdx);
367
368 void startProcessArgumentList() { ProcessArgumentList = true; }
369 void stopProcessArgumentList() { ProcessArgumentList = false; }
370
371 LLVM_ABI void processFiles();
372 LLVM_ABI void processLines();
374
375 LLVM_ABI void printRecords(raw_ostream &OS) const;
376
379 TypeIndex TI, LVElement *Element);
381 LVElement *Element);
383 TypeIndex TI, LVElement *Element);
385 TypeIndex TI, LVElement *Element);
387 TypeIndex TI, LVElement *Element);
389 TypeIndex TI, LVElement *Element);
391 TypeIndex TI, LVElement *Element);
393 TypeIndex TI, LVElement *Element);
395 LVElement *Element);
397 TypeIndex TI, LVElement *Element);
399 TypeIndex TI, LVElement *Element);
401 TypeIndex TI, LVElement *Element);
403 MethodOverloadListRecord &Overloads,
404 TypeIndex TI, LVElement *Element);
406 TypeIndex TI, LVElement *Element);
408 TypeIndex TI, LVElement *Element);
410 TypeIndex TI, LVElement *Element);
412 TypeIndex TI, LVElement *Element);
414 TypeIndex TI, LVElement *Element);
416 TypeIndex TI, LVElement *Element);
418 TypeIndex TI, LVElement *Element);
420 TypeIndex TI, LVElement *Element);
422 UdtSourceLineRecord &SourceLine, TypeIndex TI,
423 LVElement *Element);
425 UdtModSourceLineRecord &ModSourceLine,
426 TypeIndex TI, LVElement *Element);
428 TypeIndex TI, LVElement *Element);
430 TypeIndex TI, LVElement *Element);
431
434 TypeIndex TI, LVElement *Element);
437 LVElement *Element);
439 EnumeratorRecord &Enum, TypeIndex TI,
440 LVElement *Element);
443 LVElement *Element);
446 LVElement *Element);
448 OneMethodRecord &Method, TypeIndex TI,
449 LVElement *Element);
452 LVElement *Element);
455 LVElement *Element);
457 TypeIndex TI, LVElement *Element);
460 LVElement *Element);
461
462 template <typename T>
464 TypeVisitorCallbacks &Callbacks, TypeIndex TI,
465 LVElement *Element) {
466 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
467 T KnownRecord(RK);
468 if (Error Err = Callbacks.visitKnownMember(Record, KnownRecord))
469 return Err;
470 if (Error Err = visitKnownMember(Record, KnownRecord, TI, Element))
471 return Err;
472 return Error::success();
473 }
474
475 template <typename T>
477 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.kind());
478 T KnownRecord(RK);
480 const_cast<CVType &>(Record), KnownRecord))
481 return Err;
482 if (Error Err = visitKnownRecord(Record, KnownRecord, TI, Element))
483 return Err;
484 return Error::success();
485 }
486
488 TypeVisitorCallbacks &Callbacks,
489 TypeIndex TI, LVElement *Element);
491 LVElement *Element);
492};
493
494} // namespace logicalview
495} // namespace llvm
496
497#endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H
static std::string getLinkageName(GlobalValue::LinkageTypes LT)
static Error visitKnownRecord(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
#define LLVM_ABI
Definition Compiler.h:213
DXIL Resource Access
static LVOptions Options
Definition LVOptions.cpp:25
#define T
OptimizedStructLayoutField Field
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Provides read only access to a subclass of BinaryStream.
This is an important base class in LLVM.
Definition Constant.h:43
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
Represents a read-only view of a CodeView string table.
S_DEFRANGE_REGISTER_REL_INDIR.
Provides amortized O(1) random access to a CodeView type stream.
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
Definition TypeRecord.h:914
For method overload sets. LF_METHOD.
Definition TypeRecord.h:764
static Error deserializeAs(CVType &CVT, T &Record)
A 32-bit type reference.
Definition TypeIndex.h:97
static TypeIndex None()
Definition TypeIndex.h:149
void addInlineeInfo(TypeIndex TI, uint32_t LineNumber, StringRef Filename)
LLVM_ABI Error visitKnownRecord(CVType &Record, ArgListRecord &Args, TypeIndex TI, LVElement *Element)
LLVM_ABI void printRecords(raw_ostream &OS) const
LLVM_ABI void printTypeEnd(CVType &Record)
LLVM_ABI Error visitMemberRecord(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks, TypeIndex TI, LVElement *Element)
LLVM_ABI Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base, TypeIndex TI, LVElement *Element)
LLVM_ABI void printMemberEnd(CVMemberRecord &Record)
LLVM_ABI void printMemberAttributes(MemberAttributes Attrs)
void setCompileUnitName(std::string Name)
LLVM_ABI Error inlineSiteAnnotation(LVScope *AbstractFunction, LVScope *InlinedFunction, InlineSiteSym &InlineSite)
LLVM_ABI LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W, llvm::pdb::InputFile &Input)
LLVM_ABI void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx)
LLVM_ABI Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI)
void setInput(std::shared_ptr< LazyRandomTypeCollection > PrecompHeader)
Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks, TypeIndex TI, LVElement *Element)
LLVM_ABI Error visitUnknownType(CVType &Record, TypeIndex TI)
LLVM_ABI void printMemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Options)
void setInput(std::shared_ptr< llvm::pdb::InputFile > TypeServer)
LLVM_ABI void addElement(LVScope *Scope, bool IsCompileUnit)
LLVM_ABI void printTypeBegin(CVType &Record, TypeIndex TI, LVElement *Element, uint32_t StreamIdx)
LLVM_ABI LVElement * getElement(uint32_t StreamIdx, TypeIndex TI, LVScope *Parent=nullptr)
LLVM_ABI void printMemberBegin(CVMemberRecord &Record, TypeIndex TI, LVElement *Element, uint32_t StreamIdx)
LLVM_ABI Error finishVisitation(CVType &Record, TypeIndex TI, LVElement *Element)
Error visitKnownRecord(CVType &Record, TypeIndex TI, LVElement *Element)
LLVM_ABI LVElement * createElement(TypeLeafKind Kind)
LVSymbolVisitorDelegate(LVCodeViewReader *Reader, const llvm::object::SectionRef &Section, const llvm::object::COFFObjectFile *Obj, StringRef SectionContents)
uint32_t getRecordOffset(BinaryStreamReader Reader) override
LVSymbolVisitor(LVCodeViewReader *Reader, ScopedPrinter &W, LVLogicalVisitor *LogicalVisitor, LazyRandomTypeCollection &Types, LazyRandomTypeCollection &Ids, LVSymbolVisitorDelegate *ObjDelegate, LVShared *Shared)
LVTypeVisitor(ScopedPrinter &W, LVLogicalVisitor *LogicalVisitor, LazyRandomTypeCollection &Types, LazyRandomTypeCollection &Ids, uint32_t StreamIdx, LVShared *Shared)
This is a value type class that represents a single section in the list of sections in the object fil...
Definition ObjectFile.h:83
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
MethodKind
Part of member attribute flags. (CV_methodprop_e)
Definition CodeView.h:252
CVRecord< TypeLeafKind > CVType
Definition CVRecord.h:64
CVRecord< SymbolKind > CVSymbol
Definition CVRecord.h:65
MethodOptions
Equivalent to CV_fldattr_t bitfield.
Definition CodeView.h:263
MemberAccess
Source-level access specifier. (CV_access_e)
Definition CodeView.h:244
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition CodeView.h:34
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
Definition CodeView.h:27
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
Definition CodeView.h:48
This is an optimization pass for GlobalISel generic memory operations.
std::tuple< uint64_t, uint32_t > InlineSite
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
Equvalent to CV_fldattr_t in cvinfo.h.
Definition TypeRecord.h:40