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"
19 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
20 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
21 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
22 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
23 #include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h"
24 #include "llvm/DebugInfo/PDB/Native/InputFile.h"
25 #include "llvm/Object/Binary.h"
26 #include "llvm/Object/ObjectFile.h"
27 #include "llvm/Support/Error.h"
28 #include <stack>
29 #include <utility>
30 
31 namespace llvm {
32 namespace logicalview {
33 
34 using namespace llvm::codeview;
35 
36 class LVCodeViewReader;
37 class LVLogicalVisitor;
38 struct LVShared;
39 
40 class LVTypeVisitor final : public TypeVisitorCallbacks {
41   ScopedPrinter &W;
42   LVLogicalVisitor *LogicalVisitor;
43   LazyRandomTypeCollection &Types;
44   LazyRandomTypeCollection &Ids;
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 
60 public:
61   LVTypeVisitor(ScopedPrinter &W, LVLogicalVisitor *LogicalVisitor,
62                 LazyRandomTypeCollection &Types, LazyRandomTypeCollection &Ids,
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 
69   Error visitTypeBegin(CVType &Record) override;
70   Error visitTypeBegin(CVType &Record, TypeIndex TI) override;
71   Error visitMemberBegin(CVMemberRecord &Record) override;
72   Error visitMemberEnd(CVMemberRecord &Record) override;
73   Error visitUnknownMember(CVMemberRecord &Record) override;
74 
75   Error visitKnownRecord(CVType &Record, BuildInfoRecord &Args) override;
76   Error visitKnownRecord(CVType &Record, ClassRecord &Class) override;
77   Error visitKnownRecord(CVType &Record, EnumRecord &Enum) override;
78   Error visitKnownRecord(CVType &Record, FuncIdRecord &Func) override;
79   Error visitKnownRecord(CVType &Record, ProcedureRecord &Proc) override;
80   Error visitKnownRecord(CVType &Record, StringIdRecord &String) override;
81   Error visitKnownRecord(CVType &Record, UdtSourceLineRecord &Line) override;
82   Error visitKnownRecord(CVType &Record, UnionRecord &Union) override;
83   Error visitUnknownType(CVType &Record) override;
84 };
85 
86 class LVSymbolVisitorDelegate final : public SymbolVisitorDelegate {
87   LVCodeViewReader *Reader;
88   const llvm::object::coff_section *CoffSection;
89   StringRef SectionContents;
90 
91 public:
92   LVSymbolVisitorDelegate(LVCodeViewReader *Reader,
93                           const llvm::object::SectionRef &Section,
94                           const llvm::object::COFFObjectFile *Obj,
95                           StringRef SectionContents)
96       : Reader(Reader), SectionContents(SectionContents) {
97     CoffSection = Obj->getCOFFSection(Section);
98   }
99 
100   uint32_t getRecordOffset(BinaryStreamReader Reader) override {
101     ArrayRef<uint8_t> Data;
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;
116   DebugStringTableSubsectionRef getStringTable() override;
117 };
118 
119 class LVElement;
120 class LVScope;
121 class LVSymbol;
122 class LVType;
123 
124 // Visitor for CodeView symbol streams found in COFF object files and PDB files.
125 class LVSymbolVisitor final : public SymbolVisitorCallbacks {
126   LVCodeViewReader *Reader;
127   ScopedPrinter &W;
128   LVLogicalVisitor *LogicalVisitor;
129   LazyRandomTypeCollection &Types;
130   LazyRandomTypeCollection &Ids;
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 
179 public:
180   LVSymbolVisitor(LVCodeViewReader *Reader, ScopedPrinter &W,
181                   LVLogicalVisitor *LogicalVisitor,
182                   LazyRandomTypeCollection &Types,
183                   LazyRandomTypeCollection &Ids,
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 
190   Error visitSymbolBegin(CVSymbol &Record) override;
191   Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override;
192   Error visitSymbolEnd(CVSymbol &Record) override;
193   Error visitUnknownSymbol(CVSymbol &Record) override;
194 
195   Error visitKnownRecord(CVSymbol &Record, BlockSym &Block) override;
196   Error visitKnownRecord(CVSymbol &Record, BPRelativeSym &Local) override;
197   Error visitKnownRecord(CVSymbol &Record, BuildInfoSym &BuildInfo) override;
198   Error visitKnownRecord(CVSymbol &Record, Compile2Sym &Compile2) override;
199   Error visitKnownRecord(CVSymbol &Record, Compile3Sym &Compile3) override;
200   Error visitKnownRecord(CVSymbol &Record, ConstantSym &Constant) override;
201   Error visitKnownRecord(CVSymbol &Record, DataSym &Data) override;
202   Error visitKnownRecord(CVSymbol &Record,
203                          DefRangeFramePointerRelFullScopeSym
204                              &DefRangeFramePointerRelFullScope) override;
205   Error visitKnownRecord(
206       CVSymbol &Record,
207       DefRangeFramePointerRelSym &DefRangeFramePointerRel) override;
208   Error visitKnownRecord(CVSymbol &Record,
209                          DefRangeRegisterRelSym &DefRangeRegisterRel) override;
210   Error visitKnownRecord(CVSymbol &Record,
211                          DefRangeRegisterSym &DefRangeRegister) override;
212   Error visitKnownRecord(
213       CVSymbol &Record,
214       DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) override;
215   Error visitKnownRecord(CVSymbol &Record,
216                          DefRangeSubfieldSym &DefRangeSubfield) override;
217   Error visitKnownRecord(CVSymbol &Record, DefRangeSym &DefRange) override;
218   Error visitKnownRecord(CVSymbol &Record, FrameProcSym &FrameProc) override;
219   Error visitKnownRecord(CVSymbol &Record, InlineSiteSym &InlineSite) override;
220   Error visitKnownRecord(CVSymbol &Record, LocalSym &Local) override;
221   Error visitKnownRecord(CVSymbol &Record, ObjNameSym &ObjName) override;
222   Error visitKnownRecord(CVSymbol &Record, ProcSym &Proc) override;
223   Error visitKnownRecord(CVSymbol &Record, RegRelativeSym &Local) override;
224   Error visitKnownRecord(CVSymbol &Record, ScopeEndSym &ScopeEnd) override;
225   Error visitKnownRecord(CVSymbol &Record, Thunk32Sym &Thunk) override;
226   Error visitKnownRecord(CVSymbol &Record, UDTSym &UDT) override;
227   Error visitKnownRecord(CVSymbol &Record, UsingNamespaceSym &UN) override;
228 };
229 
230 // Visitor for CodeView types and symbols to populate elements.
231 class 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.
237   llvm::pdb::InputFile &Input;
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   }
249   LazyRandomTypeCollection &ids() {
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,
271                                    ArrayRef<uint8_t> FieldList);
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 
282 public:
283   LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W,
284                    llvm::pdb::InputFile &Input);
285 
286   // Current elements during the processing of a RecordType or RecordSymbol.
287   // They are shared with the SymbolVisitor.
288   LVElement *CurrentElement = nullptr;
289   LVScope *CurrentScope = nullptr;
290   LVSymbol *CurrentSymbol = nullptr;
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 
301   void addInlineeInfo(TypeIndex TI, uint32_t LineNumber, StringRef Filename) {
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);
307   void printMemberAttributes(MemberAttributes Attrs);
308   void printMemberAttributes(MemberAccess Access, MethodKind Kind,
309                              MethodOptions Options);
310 
311   LVElement *createElement(TypeLeafKind Kind);
312   LVElement *createElement(SymbolKind Kind);
313   LVElement *createElement(TypeIndex TI, TypeLeafKind Kind);
314 
315   // Break down the annotation byte code and calculate code and line offsets.
316   Error inlineSiteAnnotation(LVScope *AbstractFunction,
317                              LVScope *InlinedFunction,
318                              InlineSiteSym &InlineSite);
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);
355   void printTypeEnd(CVType &Record);
356   void printMemberBegin(CVMemberRecord &Record, TypeIndex TI,
357                         LVElement *Element, uint32_t StreamIdx);
358   void printMemberEnd(CVMemberRecord &Record);
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 
369   Error visitUnknownType(CVType &Record, TypeIndex TI);
370   Error visitKnownRecord(CVType &Record, ArgListRecord &Args, TypeIndex TI,
371                          LVElement *Element);
372   Error visitKnownRecord(CVType &Record, ArrayRecord &AT, TypeIndex TI,
373                          LVElement *Element);
374   Error visitKnownRecord(CVType &Record, BitFieldRecord &BF, TypeIndex TI,
375                          LVElement *Element);
376   Error visitKnownRecord(CVType &Record, BuildInfoRecord &BI, TypeIndex TI,
377                          LVElement *Element);
378   Error visitKnownRecord(CVType &Record, ClassRecord &Class, TypeIndex TI,
379                          LVElement *Element);
380   Error visitKnownRecord(CVType &Record, EnumRecord &Enum, TypeIndex TI,
381                          LVElement *Element);
382   Error visitKnownRecord(CVType &Record, FieldListRecord &FieldList,
383                          TypeIndex TI, LVElement *Element);
384   Error visitKnownRecord(CVType &Record, FuncIdRecord &Func, TypeIndex TI,
385                          LVElement *Element);
386   Error visitKnownRecord(CVType &Record, LabelRecord &LR, TypeIndex TI,
387                          LVElement *Element);
388   Error visitKnownRecord(CVType &Record, ModifierRecord &Mod, TypeIndex TI,
389                          LVElement *Element);
390   Error visitKnownRecord(CVType &Record, MemberFuncIdRecord &Id, TypeIndex TI,
391                          LVElement *Element);
392   Error visitKnownRecord(CVType &Record, MemberFunctionRecord &MF, TypeIndex TI,
393                          LVElement *Element);
394   Error visitKnownRecord(CVType &Record, MethodOverloadListRecord &Overloads,
395                          TypeIndex TI, LVElement *Element);
396   Error visitKnownRecord(CVType &Record, PointerRecord &Ptr, TypeIndex TI,
397                          LVElement *Element);
398   Error visitKnownRecord(CVType &Record, ProcedureRecord &Proc, TypeIndex TI,
399                          LVElement *Element);
400   Error visitKnownRecord(CVType &Record, UnionRecord &Union, TypeIndex TI,
401                          LVElement *Element);
402   Error visitKnownRecord(CVType &Record, TypeServer2Record &TS, TypeIndex TI,
403                          LVElement *Element);
404   Error visitKnownRecord(CVType &Record, VFTableRecord &VFT, TypeIndex TI,
405                          LVElement *Element);
406   Error visitKnownRecord(CVType &Record, VFTableShapeRecord &Shape,
407                          TypeIndex TI, LVElement *Element);
408   Error visitKnownRecord(CVType &Record, StringListRecord &Strings,
409                          TypeIndex TI, LVElement *Element);
410   Error visitKnownRecord(CVType &Record, StringIdRecord &String, TypeIndex TI,
411                          LVElement *Element);
412   Error visitKnownRecord(CVType &Record, UdtSourceLineRecord &SourceLine,
413                          TypeIndex TI, LVElement *Element);
414   Error visitKnownRecord(CVType &Record, UdtModSourceLineRecord &ModSourceLine,
415                          TypeIndex TI, LVElement *Element);
416   Error visitKnownRecord(CVType &Record, PrecompRecord &Precomp, TypeIndex TI,
417                          LVElement *Element);
418   Error visitKnownRecord(CVType &Record, EndPrecompRecord &EndPrecomp,
419                          TypeIndex TI, LVElement *Element);
420 
421   Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI);
422   Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base,
423                          TypeIndex TI, LVElement *Element);
424   Error visitKnownMember(CVMemberRecord &Record, DataMemberRecord &Field,
425                          TypeIndex TI, LVElement *Element);
426   Error visitKnownMember(CVMemberRecord &Record, EnumeratorRecord &Enum,
427                          TypeIndex TI, LVElement *Element);
428   Error visitKnownMember(CVMemberRecord &Record, ListContinuationRecord &Cont,
429                          TypeIndex TI, LVElement *Element);
430   Error visitKnownMember(CVMemberRecord &Record, NestedTypeRecord &Nested,
431                          TypeIndex TI, LVElement *Element);
432   Error visitKnownMember(CVMemberRecord &Record, OneMethodRecord &Method,
433                          TypeIndex TI, LVElement *Element);
434   Error visitKnownMember(CVMemberRecord &Record, OverloadedMethodRecord &Method,
435                          TypeIndex TI, LVElement *Element);
436   Error visitKnownMember(CVMemberRecord &Record, StaticDataMemberRecord &Field,
437                          TypeIndex TI, LVElement *Element);
438   Error visitKnownMember(CVMemberRecord &Record, VFPtrRecord &VFTable,
439                          TypeIndex TI, LVElement *Element);
440   Error visitKnownMember(CVMemberRecord &Record, VirtualBaseClassRecord &Base,
441                          TypeIndex TI, LVElement *Element);
442 
443   template <typename T>
444   Error visitKnownMember(CVMemberRecord &Record,
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>
457   Error visitKnownRecord(CVType &Record, TypeIndex TI, LVElement *Element) {
458     TypeRecordKind RK = static_cast<TypeRecordKind>(Record.kind());
459     T KnownRecord(RK);
460     if (Error Err = TypeDeserializer::deserializeAs(
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 
468   Error visitMemberRecord(CVMemberRecord &Record,
469                           TypeVisitorCallbacks &Callbacks, TypeIndex TI,
470                           LVElement *Element);
471   Error finishVisitation(CVType &Record, TypeIndex TI, LVElement *Element);
472 };
473 
474 } // namespace logicalview
475 } // namespace llvm
476 
477 #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_CODEVIEWVISITOR_H
478