LLVM 17.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/StringMap.h"
18#include "llvm/ADT/iterator.h"
25#include "llvm/Object/Binary.h"
27#include "llvm/Support/Error.h"
28#include <stack>
29#include <utility>
30
31namespace llvm {
32namespace logicalview {
33
34using namespace llvm::codeview;
35
36class LVCodeViewReader;
37class LVLogicalVisitor;
38struct LVShared;
39
40class LVTypeVisitor final : public TypeVisitorCallbacks {
42 LVLogicalVisitor *LogicalVisitor;
45 uint32_t StreamIdx;
46 LVShared *Shared = nullptr;
47
48 // In a PDB, a type index may refer to a type (TPI) or an item ID (IPI).
49 // In a COFF or PDB (/Z7), the type index always refer to a type (TPI).
50 // When creating logical elements, we must access the correct element
51 // table, while searching for a type index.
52 bool HasIds = false;
53
54 // Current type index during the types traversal.
55 TypeIndex CurrentTypeIndex = TypeIndex::None();
56
57 void printTypeIndex(StringRef FieldName, TypeIndex TI,
58 uint32_t StreamIdx) const;
59
60public:
63 uint32_t StreamIdx, LVShared *Shared)
64 : TypeVisitorCallbacks(), W(W), LogicalVisitor(LogicalVisitor),
65 Types(Types), Ids(Ids), StreamIdx(StreamIdx), Shared(Shared) {
66 HasIds = &Types != &Ids;
67 }
68
74
84};
85
87 LVCodeViewReader *Reader;
88 const llvm::object::coff_section *CoffSection;
89 StringRef SectionContents;
90
91public:
93 const llvm::object::SectionRef &Section,
95 StringRef SectionContents)
96 : Reader(Reader), SectionContents(SectionContents) {
97 CoffSection = Obj->getCOFFSection(Section);
98 }
99
102 if (Error Err = Reader.readLongestContiguousChunk(Data)) {
103 llvm::consumeError(std::move(Err));
104 return 0;
105 }
106 return Data.data() - SectionContents.bytes_begin();
107 }
108
109 void printRelocatedField(StringRef Label, uint32_t RelocOffset,
110 uint32_t Offset, StringRef *RelocSym = nullptr);
111
112 void getLinkageName(uint32_t RelocOffset, uint32_t Offset,
113 StringRef *RelocSym = nullptr);
114
115 StringRef getFileNameForFileOffset(uint32_t FileOffset) override;
117};
118
119class LVElement;
120class LVScope;
121class LVSymbol;
122class LVType;
123
124// Visitor for CodeView symbol streams found in COFF object files and PDB files.
126 LVCodeViewReader *Reader;
127 ScopedPrinter &W;
128 LVLogicalVisitor *LogicalVisitor;
131 LVSymbolVisitorDelegate *ObjDelegate;
132 LVShared *Shared;
133
134 // Symbol offset when processing PDB streams.
135 uint32_t CurrentOffset = 0;
136 // Current object name collected from S_OBJNAME.
137 StringRef CurrentObjectName;
138 // Last symbol processed by S_LOCAL.
139 LVSymbol *LocalSymbol = nullptr;
140
141 bool HasIds;
142 bool InFunctionScope = false;
143 bool IsCompileUnit = false;
144
145 // Register for the locals and parameters symbols in the current frame.
146 RegisterId LocalFrameRegister = RegisterId::NONE;
147 RegisterId ParamFrameRegister = RegisterId::NONE;
148
149 void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
150 uint32_t RelocationOffset);
151 void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
152 void printTypeIndex(StringRef FieldName, TypeIndex TI) const;
153
154 // Return true if this symbol is a Compile Unit.
155 bool symbolIsCompileUnit(SymbolKind Kind) {
156 switch (Kind) {
157 case SymbolKind::S_COMPILE2:
158 case SymbolKind::S_COMPILE3:
159 return true;
160 default:
161 return false;
162 }
163 }
164
165 // Determine symbol kind (local or parameter).
166 void determineSymbolKind(LVSymbol *Symbol, RegisterId Register) {
167 if (Register == LocalFrameRegister) {
168 Symbol->setIsVariable();
169 return;
170 }
171 if (Register == ParamFrameRegister) {
172 Symbol->setIsParameter();
173 return;
174 }
175 // Assume is a variable.
176 Symbol->setIsVariable();
177 }
178
179public:
181 LVLogicalVisitor *LogicalVisitor,
184 LVSymbolVisitorDelegate *ObjDelegate, LVShared *Shared)
185 : Reader(Reader), W(W), LogicalVisitor(LogicalVisitor), Types(Types),
186 Ids(Ids), ObjDelegate(ObjDelegate), Shared(Shared) {
187 HasIds = &Types != &Ids;
188 }
189
194
197 Error visitKnownRecord(CVSymbol &Record, BuildInfoSym &BuildInfo) override;
198 Error visitKnownRecord(CVSymbol &Record, Compile2Sym &Compile2) override;
199 Error visitKnownRecord(CVSymbol &Record, Compile3Sym &Compile3) override;
204 &DefRangeFramePointerRelFullScope) override;
207 DefRangeFramePointerRelSym &DefRangeFramePointerRel) override;
209 DefRangeRegisterRelSym &DefRangeRegisterRel) override;
211 DefRangeRegisterSym &DefRangeRegister) override;
214 DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) override;
216 DefRangeSubfieldSym &DefRangeSubfield) override;
217 Error visitKnownRecord(CVSymbol &Record, DefRangeSym &DefRange) override;
218 Error visitKnownRecord(CVSymbol &Record, FrameProcSym &FrameProc) override;
221 Error visitKnownRecord(CVSymbol &Record, ObjNameSym &ObjName) override;
222 Error visitKnownRecord(CVSymbol &Record, ProcSym &Proc) override;
224 Error visitKnownRecord(CVSymbol &Record, ScopeEndSym &ScopeEnd) override;
228};
229
230// Visitor for CodeView types and symbols to populate elements.
231class LVLogicalVisitor final {
232 LVCodeViewReader *Reader;
233 ScopedPrinter &W;
234
235 // Encapsulates access to the input file and any dependent type server,
236 // including any precompiled header object.
238 std::shared_ptr<llvm::pdb::InputFile> TypeServer = nullptr;
239 std::shared_ptr<LazyRandomTypeCollection> PrecompHeader = nullptr;
240
241 std::shared_ptr<LVShared> Shared;
242
243 // Object files have only one type stream that contains both types and ids.
244 // Precompiled header objects don't contain an IPI stream. Use the TPI.
245 LazyRandomTypeCollection &types() {
246 return TypeServer ? TypeServer->types()
247 : (PrecompHeader ? *PrecompHeader : Input.types());
248 }
250 return TypeServer ? TypeServer->ids()
251 : (PrecompHeader ? *PrecompHeader : Input.ids());
252 }
253
254 using LVScopeStack = std::stack<LVScope *>;
255 LVScopeStack ScopeStack;
256 LVScope *ReaderParent = nullptr;
257 LVScope *ReaderScope = nullptr;
258 bool InCompileUnitScope = false;
259
260 // Allow processing of argument list.
261 bool ProcessArgumentList = false;
262 StringRef OverloadedMethodName;
263 std::string CompileUnitName;
264
265 // Inlined functions source information.
266 using LVInlineeEntry = std::pair<uint32_t, StringRef>;
267 using LVInlineeInfo = std::map<TypeIndex, LVInlineeEntry>;
268 LVInlineeInfo InlineeInfo;
269
270 Error visitFieldListMemberStream(TypeIndex TI, LVElement *Element,
272
273 LVType *createBaseType(TypeIndex TI, StringRef TypeName);
274 LVType *createPointerType(TypeIndex TI, StringRef TypeName);
275 LVSymbol *createParameter(TypeIndex TI, StringRef Name, LVScope *Parent);
276 LVSymbol *createParameter(LVElement *Element, StringRef Name,
277 LVScope *Parent);
278 void createDataMember(CVMemberRecord &Record, LVScope *Parent, StringRef Name,
279 TypeIndex Type, MemberAccess Access);
280 void createParents(StringRef ScopedName, LVElement *Element);
281
282public:
284 llvm::pdb::InputFile &Input);
285
286 // Current elements during the processing of a RecordType or RecordSymbol.
287 // They are shared with the SymbolVisitor.
291 LVType *CurrentType = nullptr;
292
293 // Input source in the case of type server or precompiled header.
294 void setInput(std::shared_ptr<llvm::pdb::InputFile> TypeServer) {
295 this->TypeServer = TypeServer;
296 }
297 void setInput(std::shared_ptr<LazyRandomTypeCollection> PrecompHeader) {
298 this->PrecompHeader = PrecompHeader;
299 }
300
302 InlineeInfo.emplace(std::piecewise_construct, std::forward_as_tuple(TI),
303 std::forward_as_tuple(LineNumber, Filename));
304 }
305
306 void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx);
310
314
315 // Break down the annotation byte code and calculate code and line offsets.
316 Error inlineSiteAnnotation(LVScope *AbstractFunction,
317 LVScope *InlinedFunction,
319
320 void pushScope(LVScope *Scope) {
321 ScopeStack.push(ReaderParent);
322 ReaderParent = ReaderScope;
323 ReaderScope = Scope;
324 }
325 void popScope() {
326 ReaderScope = ReaderParent;
327 ReaderParent = ScopeStack.top();
328 ScopeStack.pop();
329 }
330 void closeScope() {
331 if (InCompileUnitScope) {
332 InCompileUnitScope = false;
333 popScope();
334 }
335 }
336 void setRoot(LVScope *Root) { ReaderScope = Root; }
337
338 void addElement(LVScope *Scope, bool IsCompileUnit);
339 void addElement(LVSymbol *Symbol);
340 void addElement(LVType *Type);
341
342 std::string getCompileUnitName() { return CompileUnitName; }
343 void setCompileUnitName(std::string Name) {
344 CompileUnitName = std::move(Name);
345 }
346
347 LVElement *getElement(uint32_t StreamIdx, TypeIndex TI,
348 LVScope *Parent = nullptr);
349 LVShared *getShared() { return Shared.get(); }
350
351 LVScope *getReaderScope() const { return ReaderScope; }
352
353 void printTypeBegin(CVType &Record, TypeIndex TI, LVElement *Element,
354 uint32_t StreamIdx);
357 LVElement *Element, uint32_t StreamIdx);
359
360 void startProcessArgumentList() { ProcessArgumentList = true; }
361 void stopProcessArgumentList() { ProcessArgumentList = false; }
362
363 void processFiles();
364 void processLines();
365 void processNamespaces();
366
367 void printRecords(raw_ostream &OS) const;
368
371 LVElement *Element);
373 LVElement *Element);
375 LVElement *Element);
377 LVElement *Element);
379 LVElement *Element);
381 LVElement *Element);
383 TypeIndex TI, LVElement *Element);
385 LVElement *Element);
387 LVElement *Element);
389 LVElement *Element);
391 LVElement *Element);
393 LVElement *Element);
395 TypeIndex TI, LVElement *Element);
397 LVElement *Element);
399 LVElement *Element);
401 LVElement *Element);
403 LVElement *Element);
405 LVElement *Element);
407 TypeIndex TI, LVElement *Element);
409 TypeIndex TI, LVElement *Element);
411 LVElement *Element);
413 TypeIndex TI, LVElement *Element);
415 TypeIndex TI, LVElement *Element);
417 LVElement *Element);
419 TypeIndex TI, LVElement *Element);
420
423 TypeIndex TI, LVElement *Element);
425 TypeIndex TI, LVElement *Element);
427 TypeIndex TI, LVElement *Element);
429 TypeIndex TI, LVElement *Element);
431 TypeIndex TI, LVElement *Element);
433 TypeIndex TI, LVElement *Element);
435 TypeIndex TI, LVElement *Element);
437 TypeIndex TI, LVElement *Element);
439 TypeIndex TI, LVElement *Element);
441 TypeIndex TI, LVElement *Element);
442
443 template <typename T>
445 TypeVisitorCallbacks &Callbacks, TypeIndex TI,
446 LVElement *Element) {
447 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
448 T KnownRecord(RK);
449 if (Error Err = Callbacks.visitKnownMember(Record, KnownRecord))
450 return Err;
451 if (Error Err = visitKnownMember(Record, KnownRecord, TI, Element))
452 return Err;
453 return Error::success();
454 }
455
456 template <typename T>
458 TypeRecordKind RK = static_cast<TypeRecordKind>(Record.kind());
459 T KnownRecord(RK);
461 const_cast<CVType &>(Record), KnownRecord))
462 return Err;
463 if (Error Err = visitKnownRecord(Record, KnownRecord, TI, Element))
464 return Err;
465 return Error::success();
466 }
467
469 TypeVisitorCallbacks &Callbacks, TypeIndex TI,
470 LVElement *Element);
472};
473
474} // namespace logicalview
475} // namespace llvm
476
477#endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H
This file defines the StringMap class.
static LVOptions Options
Definition: LVOptions.cpp:25
raw_pwrite_stream & OS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Provides read only access to a subclass of BinaryStream.
Error readLongestContiguousChunk(ArrayRef< uint8_t > &Buffer)
Read as much as possible from the underlying string at the current offset without invoking a copy,...
This is an important base class in LLVM.
Definition: Constant.h:41
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
const unsigned char * bytes_begin() const
Definition: StringRef.h:115
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Represents a read-only view of a CodeView string table.
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:915
For method overload sets. LF_METHOD.
Definition: TypeRecord.h:765
static Error deserializeAs(CVType &CVT, T &Record)
A 32-bit type reference.
Definition: TypeIndex.h:96
static TypeIndex None()
Definition: TypeIndex.h:148
void addInlineeInfo(TypeIndex TI, uint32_t LineNumber, StringRef Filename)
Error visitKnownRecord(CVType &Record, ArgListRecord &Args, TypeIndex TI, LVElement *Element)
void printRecords(raw_ostream &OS) const
Error visitMemberRecord(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks, TypeIndex TI, LVElement *Element)
Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base, TypeIndex TI, LVElement *Element)
void printMemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Options)
void printMemberEnd(CVMemberRecord &Record)
void setCompileUnitName(std::string Name)
void printMemberAttributes(MemberAttributes Attrs)
Error inlineSiteAnnotation(LVScope *AbstractFunction, LVScope *InlinedFunction, InlineSiteSym &InlineSite)
void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx)
Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI)
void setInput(std::shared_ptr< LazyRandomTypeCollection > PrecompHeader)
Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks, TypeIndex TI, LVElement *Element)
Error visitUnknownType(CVType &Record, TypeIndex TI)
void setInput(std::shared_ptr< llvm::pdb::InputFile > TypeServer)
void addElement(LVScope *Scope, bool IsCompileUnit)
void printTypeBegin(CVType &Record, TypeIndex TI, LVElement *Element, uint32_t StreamIdx)
LVElement * getElement(uint32_t StreamIdx, TypeIndex TI, LVScope *Parent=nullptr)
void printMemberBegin(CVMemberRecord &Record, TypeIndex TI, LVElement *Element, uint32_t StreamIdx)
Error finishVisitation(CVType &Record, TypeIndex TI, LVElement *Element)
Error visitKnownRecord(CVType &Record, TypeIndex TI, LVElement *Element)
LVElement * createElement(TypeLeafKind Kind)
LVSymbolVisitorDelegate(LVCodeViewReader *Reader, const llvm::object::SectionRef &Section, const llvm::object::COFFObjectFile *Obj, StringRef SectionContents)
void getLinkageName(uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym=nullptr)
uint32_t getRecordOffset(BinaryStreamReader Reader) override
void printRelocatedField(StringRef Label, uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym=nullptr)
DebugStringTableSubsectionRef getStringTable() override
StringRef getFileNameForFileOffset(uint32_t FileOffset) override
Error visitSymbolEnd(CVSymbol &Record) override
LVSymbolVisitor(LVCodeViewReader *Reader, ScopedPrinter &W, LVLogicalVisitor *LogicalVisitor, LazyRandomTypeCollection &Types, LazyRandomTypeCollection &Ids, LVSymbolVisitorDelegate *ObjDelegate, LVShared *Shared)
Error visitKnownRecord(CVSymbol &Record, BlockSym &Block) override
Error visitSymbolBegin(CVSymbol &Record) override
Error visitUnknownSymbol(CVSymbol &Record) override
Action to take on unknown symbols. By default, they are ignored.
Error visitMemberEnd(CVMemberRecord &Record) override
LVTypeVisitor(ScopedPrinter &W, LVLogicalVisitor *LogicalVisitor, LazyRandomTypeCollection &Types, LazyRandomTypeCollection &Ids, uint32_t StreamIdx, LVShared *Shared)
Error visitUnknownMember(CVMemberRecord &Record) override
Error visitTypeBegin(CVType &Record) override
Paired begin/end actions for all types.
Error visitMemberBegin(CVMemberRecord &Record) override
Error visitKnownRecord(CVType &Record, BuildInfoRecord &Args) override
Error visitUnknownType(CVType &Record) override
Action to take on unknown types. By default, they are ignored.
const coff_section * getCOFFSection(const SectionRef &Section) const
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:80
codeview::LazyRandomTypeCollection & types()
Definition: InputFile.cpp:456
codeview::LazyRandomTypeCollection & ids()
Definition: InputFile.cpp:460
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
MethodKind
Part of member attribute flags. (CV_methodprop_e)
Definition: CodeView.h:272
MethodOptions
Equivalent to CV_fldattr_t bitfield.
Definition: CodeView.h:283
MemberAccess
Source-level access specifier. (CV_access_e)
Definition: CodeView.h:264
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:33
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
Definition: CodeView.h:26
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:47
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::tuple< uint64_t, uint32_t > InlineSite
Definition: MCPseudoProbe.h:99
@ Mod
The access may modify the value stored in memory.
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
Equvalent to CV_fldattr_t in cvinfo.h.
Definition: TypeRecord.h:40