xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 
30 namespace llvm {
31 namespace logicalview {
32 
33 using namespace llvm::codeview;
34 
35 class LVCodeViewReader;
36 class LVLogicalVisitor;
37 struct LVShared;
38 
39 class 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 
59 public:
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 
85 class LVSymbolVisitorDelegate final : public SymbolVisitorDelegate {
86   LVCodeViewReader *Reader;
87   const llvm::object::coff_section *CoffSection;
88   StringRef SectionContents;
89 
90 public:
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(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 
118 class LVElement;
119 class LVScope;
120 class LVSymbol;
121 class LVType;
122 
123 // Visitor for CodeView symbol streams found in COFF object files and PDB files.
124 class 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 
178 public:
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.
232 class 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 
283 public:
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(std::piecewise_construct, std::forward_as_tuple(TI),
304                         std::forward_as_tuple(LineNumber, 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(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