1 | //===-- LVCodeViewVisitor.cpp ---------------------------------------------===// |
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 implements the LVCodeViewVisitor class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h" |
14 | #include "llvm/BinaryFormat/Magic.h" |
15 | #include "llvm/DebugInfo/CodeView/EnumTables.h" |
16 | #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" |
17 | #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" |
18 | #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" |
19 | #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" |
20 | #include "llvm/DebugInfo/LogicalView/Core/LVScope.h" |
21 | #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h" |
22 | #include "llvm/DebugInfo/LogicalView/Core/LVType.h" |
23 | #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h" |
24 | #include "llvm/DebugInfo/PDB/Native/InputFile.h" |
25 | #include "llvm/DebugInfo/PDB/Native/PDBFile.h" |
26 | #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" |
27 | #include "llvm/DebugInfo/PDB/Native/TpiStream.h" |
28 | #include "llvm/Demangle/Demangle.h" |
29 | #include "llvm/Object/COFF.h" |
30 | #include "llvm/Support/Error.h" |
31 | #include "llvm/Support/FormatAdapters.h" |
32 | #include "llvm/Support/FormatVariadic.h" |
33 | |
34 | using namespace llvm; |
35 | using namespace llvm::codeview; |
36 | using namespace llvm::object; |
37 | using namespace llvm::pdb; |
38 | using namespace llvm::logicalview; |
39 | |
40 | #define DEBUG_TYPE "CodeViewUtilities" |
41 | |
42 | namespace llvm { |
43 | namespace logicalview { |
44 | |
45 | static TypeIndex getTrueType(TypeIndex &TI) { |
46 | // Dealing with a MSVC generated PDB, we encountered a type index with the |
47 | // value of: 0x0280xxxx where xxxx=0000. |
48 | // |
49 | // There is some documentation about type indices: |
50 | // https://llvm.org/docs/PDB/TpiStream.html |
51 | // |
52 | // A type index is a 32-bit integer that uniquely identifies a type inside |
53 | // of an object file’s .debug$T section or a PDB file’s TPI or IPI stream. |
54 | // The value of the type index for the first type record from the TPI stream |
55 | // is given by the TypeIndexBegin member of the TPI Stream Header although |
56 | // in practice this value is always equal to 0x1000 (4096). |
57 | // |
58 | // Any type index with a high bit set is considered to come from the IPI |
59 | // stream, although this appears to be more of a hack, and LLVM does not |
60 | // generate type indices of this nature. They can, however, be observed in |
61 | // Microsoft PDBs occasionally, so one should be prepared to handle them. |
62 | // Note that having the high bit set is not a necessary condition to |
63 | // determine whether a type index comes from the IPI stream, it is only |
64 | // sufficient. |
65 | LLVM_DEBUG( |
66 | { dbgs() << "Index before: " << HexNumber(TI.getIndex()) << "\n" ; }); |
67 | TI.setIndex(TI.getIndex() & 0x0000ffff); |
68 | LLVM_DEBUG( |
69 | { dbgs() << "Index after: " << HexNumber(TI.getIndex()) << "\n" ; }); |
70 | return TI; |
71 | } |
72 | |
73 | static const EnumEntry<TypeLeafKind> LeafTypeNames[] = { |
74 | #define CV_TYPE(enum, val) {#enum, enum}, |
75 | #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" |
76 | }; |
77 | |
78 | // Return the type name pointed by the type index. It uses the kind to query |
79 | // the associated name for the record type. |
80 | static StringRef getRecordName(LazyRandomTypeCollection &Types, TypeIndex TI) { |
81 | if (TI.isSimple()) |
82 | return {}; |
83 | |
84 | StringRef RecordName; |
85 | CVType CVReference = Types.getType(Index: TI); |
86 | auto GetName = [&](auto Record) { |
87 | if (Error Err = TypeDeserializer::deserializeAs( |
88 | const_cast<CVType &>(CVReference), Record)) |
89 | consumeError(Err: std::move(Err)); |
90 | else |
91 | RecordName = Record.getName(); |
92 | }; |
93 | |
94 | TypeRecordKind RK = static_cast<TypeRecordKind>(CVReference.kind()); |
95 | if (RK == TypeRecordKind::Class || RK == TypeRecordKind::Struct) |
96 | GetName(ClassRecord(RK)); |
97 | else if (RK == TypeRecordKind::Union) |
98 | GetName(UnionRecord(RK)); |
99 | else if (RK == TypeRecordKind::Enum) |
100 | GetName(EnumRecord(RK)); |
101 | |
102 | return RecordName; |
103 | } |
104 | |
105 | } // namespace logicalview |
106 | } // namespace llvm |
107 | |
108 | #undef DEBUG_TYPE |
109 | #define DEBUG_TYPE "CodeViewDataVisitor" |
110 | |
111 | namespace llvm { |
112 | namespace logicalview { |
113 | |
114 | // Keeps the type indexes with line information. |
115 | using LVLineRecords = std::vector<TypeIndex>; |
116 | |
117 | namespace { |
118 | |
119 | class LVTypeRecords { |
120 | LVShared *Shared = nullptr; |
121 | |
122 | // Logical elements associated to their CodeView Type Index. |
123 | using RecordEntry = std::pair<TypeLeafKind, LVElement *>; |
124 | using RecordTable = std::map<TypeIndex, RecordEntry>; |
125 | RecordTable RecordFromTypes; |
126 | RecordTable RecordFromIds; |
127 | |
128 | using NameTable = std::map<StringRef, TypeIndex>; |
129 | NameTable NameFromTypes; |
130 | NameTable NameFromIds; |
131 | |
132 | public: |
133 | LVTypeRecords(LVShared *Shared) : Shared(Shared) {} |
134 | |
135 | void add(uint32_t StreamIdx, TypeIndex TI, TypeLeafKind Kind, |
136 | LVElement *Element = nullptr); |
137 | void add(uint32_t StreamIdx, TypeIndex TI, StringRef Name); |
138 | LVElement *find(uint32_t StreamIdx, TypeIndex TI, bool Create = true); |
139 | TypeIndex find(uint32_t StreamIdx, StringRef Name); |
140 | }; |
141 | |
142 | class LVForwardReferences { |
143 | // Forward reference and its definitions (Name as key). |
144 | using ForwardEntry = std::pair<TypeIndex, TypeIndex>; |
145 | using ForwardTypeNames = std::map<StringRef, ForwardEntry>; |
146 | ForwardTypeNames ForwardTypesNames; |
147 | |
148 | // Forward reference and its definition (TypeIndex as key). |
149 | using ForwardType = std::map<TypeIndex, TypeIndex>; |
150 | ForwardType ForwardTypes; |
151 | |
152 | // Forward types and its references. |
153 | void add(TypeIndex TIForward, TypeIndex TIReference) { |
154 | ForwardTypes.emplace(args&: TIForward, args&: TIReference); |
155 | } |
156 | |
157 | void add(StringRef Name, TypeIndex TIForward) { |
158 | auto [It, Inserted] = |
159 | ForwardTypesNames.try_emplace(k: Name, args&: TIForward, args: TypeIndex::None()); |
160 | if (!Inserted) { |
161 | // Update a recorded definition with its reference. |
162 | It->second.first = TIForward; |
163 | add(TIForward, TIReference: It->second.second); |
164 | } |
165 | } |
166 | |
167 | // Update a previously recorded forward reference with its definition. |
168 | void update(StringRef Name, TypeIndex TIReference) { |
169 | auto [It, Inserted] = |
170 | ForwardTypesNames.try_emplace(k: Name, args: TypeIndex::None(), args&: TIReference); |
171 | if (!Inserted) { |
172 | // Update the recorded forward reference with its definition. |
173 | It->second.second = TIReference; |
174 | add(TIForward: It->second.first, TIReference); |
175 | } |
176 | } |
177 | |
178 | public: |
179 | LVForwardReferences() = default; |
180 | |
181 | void record(bool IsForwardRef, StringRef Name, TypeIndex TI) { |
182 | // We are expecting for the forward references to be first. But that |
183 | // is not always the case. A name must be recorded regardless of the |
184 | // order in which the forward reference appears. |
185 | (IsForwardRef) ? add(Name, TIForward: TI) : update(Name, TIReference: TI); |
186 | } |
187 | |
188 | TypeIndex find(TypeIndex TIForward) { |
189 | auto It = ForwardTypes.find(x: TIForward); |
190 | return It != ForwardTypes.end() ? It->second : TypeIndex::None(); |
191 | } |
192 | |
193 | TypeIndex find(StringRef Name) { |
194 | auto It = ForwardTypesNames.find(x: Name); |
195 | return It != ForwardTypesNames.end() ? It->second.second |
196 | : TypeIndex::None(); |
197 | } |
198 | |
199 | // If the given TI corresponds to a reference, return the reference. |
200 | // Otherwise return the given TI. |
201 | TypeIndex remap(TypeIndex TI) { |
202 | TypeIndex Forward = find(TIForward: TI); |
203 | return Forward.isNoneType() ? TI : Forward; |
204 | } |
205 | }; |
206 | |
207 | // Namespace deduction. |
208 | class LVNamespaceDeduction { |
209 | LVShared *Shared = nullptr; |
210 | |
211 | using Names = std::map<StringRef, LVScope *>; |
212 | Names NamespaceNames; |
213 | |
214 | using LookupSet = std::set<StringRef>; |
215 | LookupSet DeducedScopes; |
216 | LookupSet UnresolvedScopes; |
217 | LookupSet IdentifiedNamespaces; |
218 | |
219 | void add(StringRef Name, LVScope *Namespace) { |
220 | if (NamespaceNames.find(x: Name) == NamespaceNames.end()) |
221 | NamespaceNames.emplace(args&: Name, args&: Namespace); |
222 | } |
223 | |
224 | public: |
225 | LVNamespaceDeduction(LVShared *Shared) : Shared(Shared) {} |
226 | |
227 | void init(); |
228 | void add(StringRef String); |
229 | LVScope *get(LVStringRefs Components); |
230 | LVScope *get(StringRef Name, bool CheckScope = true); |
231 | |
232 | // Find the logical namespace for the 'Name' component. |
233 | LVScope *find(StringRef Name) { |
234 | auto It = NamespaceNames.find(x: Name); |
235 | LVScope *Namespace = It != NamespaceNames.end() ? It->second : nullptr; |
236 | return Namespace; |
237 | } |
238 | |
239 | // For the given lexical components, return a tuple with the first entry |
240 | // being the outermost namespace and the second entry being the first |
241 | // non-namespace. |
242 | LVLexicalIndex find(LVStringRefs Components) { |
243 | if (Components.empty()) |
244 | return {}; |
245 | |
246 | LVStringRefs::size_type FirstNamespace = 0; |
247 | LVStringRefs::size_type FirstNonNamespace; |
248 | for (LVStringRefs::size_type Index = 0; Index < Components.size(); |
249 | ++Index) { |
250 | FirstNonNamespace = Index; |
251 | LookupSet::iterator Iter = IdentifiedNamespaces.find(x: Components[Index]); |
252 | if (Iter == IdentifiedNamespaces.end()) |
253 | // The component is not a namespace name. |
254 | break; |
255 | } |
256 | return std::make_tuple(args&: FirstNamespace, args&: FirstNonNamespace); |
257 | } |
258 | }; |
259 | |
260 | // Strings. |
261 | class LVStringRecords { |
262 | using StringEntry = std::tuple<uint32_t, std::string, LVScopeCompileUnit *>; |
263 | using StringIds = std::map<TypeIndex, StringEntry>; |
264 | StringIds Strings; |
265 | |
266 | public: |
267 | LVStringRecords() = default; |
268 | |
269 | void add(TypeIndex TI, StringRef String) { |
270 | static uint32_t Index = 0; |
271 | auto [It, Inserted] = Strings.try_emplace(k: TI); |
272 | if (Inserted) |
273 | It->second = std::make_tuple(args&: ++Index, args: std::string(String), args: nullptr); |
274 | } |
275 | |
276 | StringRef find(TypeIndex TI) { |
277 | StringIds::iterator Iter = Strings.find(x: TI); |
278 | return Iter != Strings.end() ? std::get<1>(t&: Iter->second) : StringRef{}; |
279 | } |
280 | |
281 | uint32_t findIndex(TypeIndex TI) { |
282 | StringIds::iterator Iter = Strings.find(x: TI); |
283 | return Iter != Strings.end() ? std::get<0>(t&: Iter->second) : 0; |
284 | } |
285 | |
286 | // Move strings representing the filenames to the compile unit. |
287 | void addFilenames(); |
288 | void addFilenames(LVScopeCompileUnit *Scope); |
289 | }; |
290 | } // namespace |
291 | |
292 | using LVTypeKinds = std::set<TypeLeafKind>; |
293 | using LVSymbolKinds = std::set<SymbolKind>; |
294 | |
295 | // The following data keeps forward information, type records, names for |
296 | // namespace deduction, strings records, line records. |
297 | // It is shared by the type visitor, symbol visitor and logical visitor and |
298 | // it is independent from the CodeViewReader. |
299 | struct LVShared { |
300 | LVCodeViewReader *Reader; |
301 | LVLogicalVisitor *Visitor; |
302 | LVForwardReferences ForwardReferences; |
303 | LVLineRecords LineRecords; |
304 | LVNamespaceDeduction NamespaceDeduction; |
305 | LVStringRecords StringRecords; |
306 | LVTypeRecords TypeRecords; |
307 | |
308 | // In order to determine which types and/or symbols records should be handled |
309 | // by the reader, we record record kinds seen by the type and symbol visitors. |
310 | // At the end of the scopes creation, the '--internal=tag' option will allow |
311 | // to print the unique record ids collected. |
312 | LVTypeKinds TypeKinds; |
313 | LVSymbolKinds SymbolKinds; |
314 | |
315 | LVShared(LVCodeViewReader *Reader, LVLogicalVisitor *Visitor) |
316 | : Reader(Reader), Visitor(Visitor), NamespaceDeduction(this), |
317 | TypeRecords(this) {} |
318 | ~LVShared() = default; |
319 | }; |
320 | } // namespace logicalview |
321 | } // namespace llvm |
322 | |
323 | void LVTypeRecords::add(uint32_t StreamIdx, TypeIndex TI, TypeLeafKind Kind, |
324 | LVElement *Element) { |
325 | RecordTable &Target = |
326 | (StreamIdx == StreamTPI) ? RecordFromTypes : RecordFromIds; |
327 | Target.emplace(args: std::piecewise_construct, args: std::forward_as_tuple(args&: TI), |
328 | args: std::forward_as_tuple(args&: Kind, args&: Element)); |
329 | } |
330 | |
331 | void LVTypeRecords::add(uint32_t StreamIdx, TypeIndex TI, StringRef Name) { |
332 | NameTable &Target = (StreamIdx == StreamTPI) ? NameFromTypes : NameFromIds; |
333 | Target.emplace(args&: Name, args&: TI); |
334 | } |
335 | |
336 | LVElement *LVTypeRecords::find(uint32_t StreamIdx, TypeIndex TI, bool Create) { |
337 | RecordTable &Target = |
338 | (StreamIdx == StreamTPI) ? RecordFromTypes : RecordFromIds; |
339 | |
340 | LVElement *Element = nullptr; |
341 | RecordTable::iterator Iter = Target.find(x: TI); |
342 | if (Iter != Target.end()) { |
343 | Element = Iter->second.second; |
344 | if (Element || !Create) |
345 | return Element; |
346 | |
347 | // Create the logical element if not found. |
348 | Element = Shared->Visitor->createElement(Kind: Iter->second.first); |
349 | if (Element) { |
350 | Element->setOffset(TI.getIndex()); |
351 | Element->setOffsetFromTypeIndex(); |
352 | Target[TI].second = Element; |
353 | } |
354 | } |
355 | return Element; |
356 | } |
357 | |
358 | TypeIndex LVTypeRecords::find(uint32_t StreamIdx, StringRef Name) { |
359 | NameTable &Target = (StreamIdx == StreamTPI) ? NameFromTypes : NameFromIds; |
360 | NameTable::iterator Iter = Target.find(x: Name); |
361 | return Iter != Target.end() ? Iter->second : TypeIndex::None(); |
362 | } |
363 | |
364 | void LVStringRecords::addFilenames() { |
365 | for (StringIds::const_reference Entry : Strings) { |
366 | StringRef Name = std::get<1>(t: Entry.second); |
367 | LVScopeCompileUnit *Scope = std::get<2>(t: Entry.second); |
368 | Scope->addFilename(Name: transformPath(Path: Name)); |
369 | } |
370 | Strings.clear(); |
371 | } |
372 | |
373 | void LVStringRecords::addFilenames(LVScopeCompileUnit *Scope) { |
374 | for (StringIds::reference Entry : Strings) |
375 | if (!std::get<2>(t&: Entry.second)) |
376 | std::get<2>(t&: Entry.second) = Scope; |
377 | } |
378 | |
379 | void LVNamespaceDeduction::add(StringRef String) { |
380 | StringRef InnerComponent; |
381 | StringRef OuterComponent; |
382 | std::tie(args&: OuterComponent, args&: InnerComponent) = getInnerComponent(Name: String); |
383 | DeducedScopes.insert(x: InnerComponent); |
384 | if (OuterComponent.size()) |
385 | UnresolvedScopes.insert(x: OuterComponent); |
386 | } |
387 | |
388 | void LVNamespaceDeduction::init() { |
389 | // We have 2 sets of names: |
390 | // - deduced scopes (class, structure, union and enum) and |
391 | // - unresolved scopes, that can represent namespaces or any deduced. |
392 | // Before creating the namespaces, we have to traverse the unresolved |
393 | // and remove any references to already deduced scopes. |
394 | LVStringRefs Components; |
395 | for (const StringRef &Unresolved : UnresolvedScopes) { |
396 | Components = getAllLexicalComponents(Name: Unresolved); |
397 | for (const StringRef &Component : Components) { |
398 | LookupSet::iterator Iter = DeducedScopes.find(x: Component); |
399 | if (Iter == DeducedScopes.end()) |
400 | IdentifiedNamespaces.insert(x: Component); |
401 | } |
402 | } |
403 | |
404 | LLVM_DEBUG({ |
405 | auto Print = [&](LookupSet &Container, const char *Title) { |
406 | auto Header = [&]() { |
407 | dbgs() << formatv("\n{0}\n" , fmt_repeat('=', 72)); |
408 | dbgs() << formatv("{0}\n" , Title); |
409 | dbgs() << formatv("{0}\n" , fmt_repeat('=', 72)); |
410 | }; |
411 | Header(); |
412 | for (const StringRef &Item : Container) |
413 | dbgs() << formatv("'{0}'\n" , Item.str().c_str()); |
414 | }; |
415 | |
416 | Print(DeducedScopes, "Deducted Scopes" ); |
417 | Print(UnresolvedScopes, "Unresolved Scopes" ); |
418 | Print(IdentifiedNamespaces, "Namespaces" ); |
419 | }); |
420 | } |
421 | |
422 | LVScope *LVNamespaceDeduction::get(LVStringRefs Components) { |
423 | LLVM_DEBUG({ |
424 | for (const StringRef &Component : Components) |
425 | dbgs() << formatv("'{0}'\n" , Component.str().c_str()); |
426 | }); |
427 | |
428 | if (Components.empty()) |
429 | return nullptr; |
430 | |
431 | // Update the namespaces relationship. |
432 | LVScope *Namespace = nullptr; |
433 | LVScope *Parent = Shared->Reader->getCompileUnit(); |
434 | for (const StringRef &Component : Components) { |
435 | // Check if we have seen the namespace. |
436 | Namespace = find(Name: Component); |
437 | if (!Namespace) { |
438 | // We have identified namespaces that are generated by MSVC. Mark them |
439 | // as 'system' so they will be excluded from the logical view. |
440 | Namespace = Shared->Reader->createScopeNamespace(); |
441 | Namespace->setTag(dwarf::DW_TAG_namespace); |
442 | Namespace->setName(Component); |
443 | Parent->addElement(Scope: Namespace); |
444 | getReader().isSystemEntry(Element: Namespace); |
445 | add(Name: Component, Namespace); |
446 | } |
447 | Parent = Namespace; |
448 | } |
449 | return Parent; |
450 | } |
451 | |
452 | LVScope *LVNamespaceDeduction::get(StringRef ScopedName, bool CheckScope) { |
453 | LVStringRefs Components = getAllLexicalComponents(Name: ScopedName); |
454 | if (CheckScope) |
455 | llvm::erase_if(C&: Components, P: [&](StringRef Component) { |
456 | LookupSet::iterator Iter = IdentifiedNamespaces.find(x: Component); |
457 | return Iter == IdentifiedNamespaces.end(); |
458 | }); |
459 | |
460 | LLVM_DEBUG( |
461 | { dbgs() << formatv("ScopedName: '{0}'\n" , ScopedName.str().c_str()); }); |
462 | |
463 | return get(Components); |
464 | } |
465 | |
466 | #undef DEBUG_TYPE |
467 | #define DEBUG_TYPE "CodeViewTypeVisitor" |
468 | |
469 | //===----------------------------------------------------------------------===// |
470 | // TypeRecord traversal. |
471 | //===----------------------------------------------------------------------===// |
472 | void LVTypeVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI, |
473 | uint32_t StreamIdx) const { |
474 | codeview::printTypeIndex(Printer&: W, FieldName, TI, |
475 | Types&: StreamIdx == StreamTPI ? Types : Ids); |
476 | } |
477 | |
478 | Error LVTypeVisitor::visitTypeBegin(CVType &Record) { |
479 | return visitTypeBegin(Record, TI: TypeIndex::fromArrayIndex(Index: Types.size())); |
480 | } |
481 | |
482 | Error LVTypeVisitor::visitTypeBegin(CVType &Record, TypeIndex TI) { |
483 | LLVM_DEBUG({ |
484 | W.getOStream() << formatTypeLeafKind(Record.kind()); |
485 | W.getOStream() << " (" << HexNumber(TI.getIndex()) << ")\n" ; |
486 | }); |
487 | |
488 | if (options().getInternalTag()) |
489 | Shared->TypeKinds.insert(x: Record.kind()); |
490 | |
491 | // The collected type records, will be use to create the logical elements |
492 | // during the symbols traversal when a type is referenced. |
493 | CurrentTypeIndex = TI; |
494 | Shared->TypeRecords.add(StreamIdx, TI, Kind: Record.kind()); |
495 | return Error::success(); |
496 | } |
497 | |
498 | Error LVTypeVisitor::visitUnknownType(CVType &Record) { |
499 | LLVM_DEBUG({ W.printNumber("Length" , uint32_t(Record.content().size())); }); |
500 | return Error::success(); |
501 | } |
502 | |
503 | Error LVTypeVisitor::visitMemberBegin(CVMemberRecord &Record) { |
504 | LLVM_DEBUG({ |
505 | W.startLine() << formatTypeLeafKind(Record.Kind); |
506 | W.getOStream() << " {\n" ; |
507 | W.indent(); |
508 | }); |
509 | return Error::success(); |
510 | } |
511 | |
512 | Error LVTypeVisitor::visitMemberEnd(CVMemberRecord &Record) { |
513 | LLVM_DEBUG({ |
514 | W.unindent(); |
515 | W.startLine() << "}\n" ; |
516 | }); |
517 | return Error::success(); |
518 | } |
519 | |
520 | Error LVTypeVisitor::visitUnknownMember(CVMemberRecord &Record) { |
521 | LLVM_DEBUG({ W.printHex("UnknownMember" , unsigned(Record.Kind)); }); |
522 | return Error::success(); |
523 | } |
524 | |
525 | // LF_BUILDINFO (TPI)/(IPI) |
526 | Error LVTypeVisitor::visitKnownRecord(CVType &Record, BuildInfoRecord &Args) { |
527 | // All the args are references into the TPI/IPI stream. |
528 | LLVM_DEBUG({ |
529 | W.printNumber("NumArgs" , static_cast<uint32_t>(Args.getArgs().size())); |
530 | ListScope Arguments(W, "Arguments" ); |
531 | for (TypeIndex Arg : Args.getArgs()) |
532 | printTypeIndex("ArgType" , Arg, StreamIPI); |
533 | }); |
534 | |
535 | // Only add the strings that hold information about filenames. They will be |
536 | // used to complete the line/file information for the logical elements. |
537 | // There are other strings holding information about namespaces. |
538 | TypeIndex TI; |
539 | StringRef String; |
540 | |
541 | // Absolute CWD path |
542 | TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::CurrentDirectory]; |
543 | String = Ids.getTypeName(Index: TI); |
544 | if (!String.empty()) |
545 | Shared->StringRecords.add(TI, String); |
546 | |
547 | // Get the compile unit name. |
548 | TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile]; |
549 | String = Ids.getTypeName(Index: TI); |
550 | if (!String.empty()) |
551 | Shared->StringRecords.add(TI, String); |
552 | LogicalVisitor->setCompileUnitName(std::string(String)); |
553 | |
554 | return Error::success(); |
555 | } |
556 | |
557 | // LF_CLASS, LF_STRUCTURE, LF_INTERFACE (TPI) |
558 | Error LVTypeVisitor::visitKnownRecord(CVType &Record, ClassRecord &Class) { |
559 | LLVM_DEBUG({ |
560 | printTypeIndex("TypeIndex" , CurrentTypeIndex, StreamTPI); |
561 | printTypeIndex("FieldListType" , Class.getFieldList(), StreamTPI); |
562 | W.printString("Name" , Class.getName()); |
563 | }); |
564 | |
565 | // Collect class name for scope deduction. |
566 | Shared->NamespaceDeduction.add(String: Class.getName()); |
567 | Shared->ForwardReferences.record(IsForwardRef: Class.isForwardRef(), Name: Class.getName(), |
568 | TI: CurrentTypeIndex); |
569 | |
570 | // Collect class name for contained scopes deduction. |
571 | Shared->TypeRecords.add(StreamIdx, TI: CurrentTypeIndex, Name: Class.getName()); |
572 | return Error::success(); |
573 | } |
574 | |
575 | // LF_ENUM (TPI) |
576 | Error LVTypeVisitor::visitKnownRecord(CVType &Record, EnumRecord &Enum) { |
577 | LLVM_DEBUG({ |
578 | printTypeIndex("TypeIndex" , CurrentTypeIndex, StreamTPI); |
579 | printTypeIndex("FieldListType" , Enum.getFieldList(), StreamTPI); |
580 | W.printString("Name" , Enum.getName()); |
581 | }); |
582 | |
583 | // Collect enum name for scope deduction. |
584 | Shared->NamespaceDeduction.add(String: Enum.getName()); |
585 | return Error::success(); |
586 | } |
587 | |
588 | // LF_FUNC_ID (TPI)/(IPI) |
589 | Error LVTypeVisitor::visitKnownRecord(CVType &Record, FuncIdRecord &Func) { |
590 | LLVM_DEBUG({ |
591 | printTypeIndex("TypeIndex" , CurrentTypeIndex, StreamTPI); |
592 | printTypeIndex("Type" , Func.getFunctionType(), StreamTPI); |
593 | printTypeIndex("Parent" , Func.getParentScope(), StreamTPI); |
594 | W.printString("Name" , Func.getName()); |
595 | }); |
596 | |
597 | // Collect function name for scope deduction. |
598 | Shared->NamespaceDeduction.add(String: Func.getName()); |
599 | return Error::success(); |
600 | } |
601 | |
602 | // LF_PROCEDURE (TPI) |
603 | Error LVTypeVisitor::visitKnownRecord(CVType &Record, ProcedureRecord &Proc) { |
604 | LLVM_DEBUG({ |
605 | printTypeIndex("TypeIndex" , CurrentTypeIndex, StreamTPI); |
606 | printTypeIndex("ReturnType" , Proc.getReturnType(), StreamTPI); |
607 | W.printNumber("NumParameters" , Proc.getParameterCount()); |
608 | printTypeIndex("ArgListType" , Proc.getArgumentList(), StreamTPI); |
609 | }); |
610 | |
611 | // Collect procedure information as they can be referenced by typedefs. |
612 | Shared->TypeRecords.add(StreamIdx: StreamTPI, TI: CurrentTypeIndex, Kind: {}); |
613 | return Error::success(); |
614 | } |
615 | |
616 | // LF_STRING_ID (TPI)/(IPI) |
617 | Error LVTypeVisitor::visitKnownRecord(CVType &Record, StringIdRecord &String) { |
618 | // No additional references are needed. |
619 | LLVM_DEBUG({ |
620 | printTypeIndex("Id" , String.getId(), StreamIPI); |
621 | W.printString("StringData" , String.getString()); |
622 | }); |
623 | return Error::success(); |
624 | } |
625 | |
626 | // LF_UDT_SRC_LINE (TPI)/(IPI) |
627 | Error LVTypeVisitor::visitKnownRecord(CVType &Record, |
628 | UdtSourceLineRecord &Line) { |
629 | // UDT and SourceFile are references into the TPI/IPI stream. |
630 | LLVM_DEBUG({ |
631 | printTypeIndex("UDT" , Line.getUDT(), StreamIPI); |
632 | printTypeIndex("SourceFile" , Line.getSourceFile(), StreamIPI); |
633 | W.printNumber("LineNumber" , Line.getLineNumber()); |
634 | }); |
635 | |
636 | Shared->LineRecords.push_back(x: CurrentTypeIndex); |
637 | return Error::success(); |
638 | } |
639 | |
640 | // LF_UNION (TPI) |
641 | Error LVTypeVisitor::visitKnownRecord(CVType &Record, UnionRecord &Union) { |
642 | LLVM_DEBUG({ |
643 | W.printNumber("MemberCount" , Union.getMemberCount()); |
644 | printTypeIndex("FieldList" , Union.getFieldList(), StreamTPI); |
645 | W.printNumber("SizeOf" , Union.getSize()); |
646 | W.printString("Name" , Union.getName()); |
647 | if (Union.hasUniqueName()) |
648 | W.printString("UniqueName" , Union.getUniqueName()); |
649 | }); |
650 | |
651 | // Collect union name for scope deduction. |
652 | Shared->NamespaceDeduction.add(String: Union.getName()); |
653 | Shared->ForwardReferences.record(IsForwardRef: Union.isForwardRef(), Name: Union.getName(), |
654 | TI: CurrentTypeIndex); |
655 | |
656 | // Collect class name for contained scopes deduction. |
657 | Shared->TypeRecords.add(StreamIdx, TI: CurrentTypeIndex, Name: Union.getName()); |
658 | return Error::success(); |
659 | } |
660 | |
661 | #undef DEBUG_TYPE |
662 | #define DEBUG_TYPE "CodeViewSymbolVisitor" |
663 | |
664 | //===----------------------------------------------------------------------===// |
665 | // SymbolRecord traversal. |
666 | //===----------------------------------------------------------------------===// |
667 | void LVSymbolVisitorDelegate::printRelocatedField(StringRef Label, |
668 | uint32_t RelocOffset, |
669 | uint32_t Offset, |
670 | StringRef *RelocSym) { |
671 | Reader->printRelocatedField(Label, CoffSection, RelocOffset, Offset, |
672 | RelocSym); |
673 | } |
674 | |
675 | void LVSymbolVisitorDelegate::getLinkageName(uint32_t RelocOffset, |
676 | uint32_t Offset, |
677 | StringRef *RelocSym) { |
678 | Reader->getLinkageName(CoffSection, RelocOffset, Offset, RelocSym); |
679 | } |
680 | |
681 | StringRef |
682 | LVSymbolVisitorDelegate::getFileNameForFileOffset(uint32_t FileOffset) { |
683 | Expected<StringRef> Name = Reader->getFileNameForFileOffset(FileOffset); |
684 | if (!Name) { |
685 | consumeError(Err: Name.takeError()); |
686 | return {}; |
687 | } |
688 | return *Name; |
689 | } |
690 | |
691 | DebugStringTableSubsectionRef LVSymbolVisitorDelegate::getStringTable() { |
692 | return Reader->CVStringTable; |
693 | } |
694 | |
695 | void LVSymbolVisitor::printLocalVariableAddrRange( |
696 | const LocalVariableAddrRange &Range, uint32_t RelocationOffset) { |
697 | DictScope S(W, "LocalVariableAddrRange" ); |
698 | if (ObjDelegate) |
699 | ObjDelegate->printRelocatedField(Label: "OffsetStart" , RelocOffset: RelocationOffset, |
700 | Offset: Range.OffsetStart); |
701 | W.printHex(Label: "ISectStart" , Value: Range.ISectStart); |
702 | W.printHex(Label: "Range" , Value: Range.Range); |
703 | } |
704 | |
705 | void LVSymbolVisitor::printLocalVariableAddrGap( |
706 | ArrayRef<LocalVariableAddrGap> Gaps) { |
707 | for (const LocalVariableAddrGap &Gap : Gaps) { |
708 | ListScope S(W, "LocalVariableAddrGap" ); |
709 | W.printHex(Label: "GapStartOffset" , Value: Gap.GapStartOffset); |
710 | W.printHex(Label: "Range" , Value: Gap.Range); |
711 | } |
712 | } |
713 | |
714 | void LVSymbolVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const { |
715 | codeview::printTypeIndex(Printer&: W, FieldName, TI, Types); |
716 | } |
717 | |
718 | Error LVSymbolVisitor::visitSymbolBegin(CVSymbol &Record) { |
719 | return visitSymbolBegin(Record, Offset: 0); |
720 | } |
721 | |
722 | Error LVSymbolVisitor::visitSymbolBegin(CVSymbol &Record, uint32_t Offset) { |
723 | SymbolKind Kind = Record.kind(); |
724 | LLVM_DEBUG({ |
725 | W.printNumber("Offset" , Offset); |
726 | W.printEnum("Begin Kind" , unsigned(Kind), getSymbolTypeNames()); |
727 | }); |
728 | |
729 | if (options().getInternalTag()) |
730 | Shared->SymbolKinds.insert(x: Kind); |
731 | |
732 | LogicalVisitor->CurrentElement = LogicalVisitor->createElement(Kind); |
733 | if (!LogicalVisitor->CurrentElement) { |
734 | LLVM_DEBUG({ |
735 | // We have an unsupported Symbol or Type Record. |
736 | // W.printEnum("Kind ignored", unsigned(Kind), getSymbolTypeNames()); |
737 | }); |
738 | return Error::success(); |
739 | } |
740 | |
741 | // Offset carried by the traversal routines when dealing with streams. |
742 | CurrentOffset = Offset; |
743 | IsCompileUnit = false; |
744 | if (!LogicalVisitor->CurrentElement->getOffsetFromTypeIndex()) |
745 | LogicalVisitor->CurrentElement->setOffset(Offset); |
746 | if (symbolOpensScope(Kind) || (IsCompileUnit = symbolIsCompileUnit(Kind))) { |
747 | assert(LogicalVisitor->CurrentScope && "Invalid scope!" ); |
748 | LogicalVisitor->addElement(Scope: LogicalVisitor->CurrentScope, IsCompileUnit); |
749 | } else { |
750 | if (LogicalVisitor->CurrentSymbol) |
751 | LogicalVisitor->addElement(Symbol: LogicalVisitor->CurrentSymbol); |
752 | if (LogicalVisitor->CurrentType) |
753 | LogicalVisitor->addElement(Type: LogicalVisitor->CurrentType); |
754 | } |
755 | |
756 | return Error::success(); |
757 | } |
758 | |
759 | Error LVSymbolVisitor::visitSymbolEnd(CVSymbol &Record) { |
760 | SymbolKind Kind = Record.kind(); |
761 | LLVM_DEBUG( |
762 | { W.printEnum("End Kind" , unsigned(Kind), getSymbolTypeNames()); }); |
763 | |
764 | if (symbolEndsScope(Kind)) { |
765 | LogicalVisitor->popScope(); |
766 | } |
767 | |
768 | return Error::success(); |
769 | } |
770 | |
771 | Error LVSymbolVisitor::visitUnknownSymbol(CVSymbol &Record) { |
772 | LLVM_DEBUG({ W.printNumber("Length" , Record.length()); }); |
773 | return Error::success(); |
774 | } |
775 | |
776 | // S_BLOCK32 |
777 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, BlockSym &Block) { |
778 | LLVM_DEBUG({ |
779 | W.printHex("CodeSize" , Block.CodeSize); |
780 | W.printHex("Segment" , Block.Segment); |
781 | W.printString("BlockName" , Block.Name); |
782 | }); |
783 | |
784 | if (LVScope *Scope = LogicalVisitor->CurrentScope) { |
785 | StringRef LinkageName; |
786 | if (ObjDelegate) |
787 | ObjDelegate->getLinkageName(RelocOffset: Block.getRelocationOffset(), Offset: Block.CodeOffset, |
788 | RelocSym: &LinkageName); |
789 | Scope->setLinkageName(LinkageName); |
790 | |
791 | if (options().getGeneralCollectRanges()) { |
792 | // Record converted segment::offset addressing for this scope. |
793 | LVAddress Addendum = Reader->getSymbolTableAddress(Name: LinkageName); |
794 | LVAddress LowPC = |
795 | Reader->linearAddress(Segment: Block.Segment, Offset: Block.CodeOffset, Addendum); |
796 | LVAddress HighPC = LowPC + Block.CodeSize - 1; |
797 | Scope->addObject(LowerAddress: LowPC, UpperAddress: HighPC); |
798 | } |
799 | } |
800 | |
801 | return Error::success(); |
802 | } |
803 | |
804 | // S_BPREL32 |
805 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
806 | BPRelativeSym &Local) { |
807 | LLVM_DEBUG({ |
808 | printTypeIndex("Type" , Local.Type); |
809 | W.printNumber("Offset" , Local.Offset); |
810 | W.printString("VarName" , Local.Name); |
811 | }); |
812 | |
813 | if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { |
814 | Symbol->setName(Local.Name); |
815 | // From the MS_Symbol_Type.pdf documentation (S_BPREL32): |
816 | // This symbol specifies symbols that are allocated on the stack for a |
817 | // procedure. For C and C++, these include the actual function parameters |
818 | // and the local non-static variables of functions. |
819 | // However, the offset for 'this' comes as a negative value. |
820 | |
821 | // Symbol was created as 'variable'; determine its real kind. |
822 | Symbol->resetIsVariable(); |
823 | |
824 | if (Local.Name == "this" ) { |
825 | Symbol->setIsParameter(); |
826 | Symbol->setIsArtificial(); |
827 | } else { |
828 | // Determine symbol kind. |
829 | bool(Local.Offset > 0) ? Symbol->setIsParameter() |
830 | : Symbol->setIsVariable(); |
831 | } |
832 | |
833 | // Update correct debug information tag. |
834 | if (Symbol->getIsParameter()) |
835 | Symbol->setTag(dwarf::DW_TAG_formal_parameter); |
836 | |
837 | LVElement *Element = LogicalVisitor->getElement(StreamIdx: StreamTPI, TI: Local.Type); |
838 | if (Element && Element->getIsScoped()) { |
839 | // We have a local type. Find its parent function. |
840 | LVScope *Parent = Symbol->getFunctionParent(); |
841 | // The element representing the type has been already finalized. If |
842 | // the type is an aggregate type, its members have been already added. |
843 | // As the type is local, its level will be changed. |
844 | |
845 | // FIXME: Currently the algorithm used to scope lambda functions is |
846 | // incorrect. Before we allocate the type at this scope, check if is |
847 | // already allocated in other scope. |
848 | if (!Element->getParentScope()) { |
849 | Parent->addElement(Element); |
850 | Element->updateLevel(Parent); |
851 | } |
852 | } |
853 | Symbol->setType(Element); |
854 | } |
855 | |
856 | return Error::success(); |
857 | } |
858 | |
859 | // S_REGREL32 |
860 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
861 | RegRelativeSym &Local) { |
862 | LLVM_DEBUG({ |
863 | printTypeIndex("Type" , Local.Type); |
864 | W.printNumber("Offset" , Local.Offset); |
865 | W.printString("VarName" , Local.Name); |
866 | }); |
867 | |
868 | if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { |
869 | Symbol->setName(Local.Name); |
870 | |
871 | // Symbol was created as 'variable'; determine its real kind. |
872 | Symbol->resetIsVariable(); |
873 | |
874 | // Check for the 'this' symbol. |
875 | if (Local.Name == "this" ) { |
876 | Symbol->setIsArtificial(); |
877 | Symbol->setIsParameter(); |
878 | } else { |
879 | // Determine symbol kind. |
880 | determineSymbolKind(Symbol, Register: Local.Register); |
881 | } |
882 | |
883 | // Update correct debug information tag. |
884 | if (Symbol->getIsParameter()) |
885 | Symbol->setTag(dwarf::DW_TAG_formal_parameter); |
886 | |
887 | LVElement *Element = LogicalVisitor->getElement(StreamIdx: StreamTPI, TI: Local.Type); |
888 | if (Element && Element->getIsScoped()) { |
889 | // We have a local type. Find its parent function. |
890 | LVScope *Parent = Symbol->getFunctionParent(); |
891 | // The element representing the type has been already finalized. If |
892 | // the type is an aggregate type, its members have been already added. |
893 | // As the type is local, its level will be changed. |
894 | |
895 | // FIXME: Currently the algorithm used to scope lambda functions is |
896 | // incorrect. Before we allocate the type at this scope, check if is |
897 | // already allocated in other scope. |
898 | if (!Element->getParentScope()) { |
899 | Parent->addElement(Element); |
900 | Element->updateLevel(Parent); |
901 | } |
902 | } |
903 | Symbol->setType(Element); |
904 | } |
905 | |
906 | return Error::success(); |
907 | } |
908 | |
909 | // S_BUILDINFO |
910 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &CVR, |
911 | BuildInfoSym &BuildInfo) { |
912 | LLVM_DEBUG({ printTypeIndex("BuildId" , BuildInfo.BuildId); }); |
913 | |
914 | CVType CVBuildType = Ids.getType(Index: BuildInfo.BuildId); |
915 | if (Error Err = LogicalVisitor->finishVisitation( |
916 | Record&: CVBuildType, TI: BuildInfo.BuildId, Element: Reader->getCompileUnit())) |
917 | return Err; |
918 | |
919 | return Error::success(); |
920 | } |
921 | |
922 | // S_COMPILE2 |
923 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
924 | Compile2Sym &Compile2) { |
925 | LLVM_DEBUG({ |
926 | W.printEnum("Language" , uint8_t(Compile2.getLanguage()), |
927 | getSourceLanguageNames()); |
928 | W.printFlags("Flags" , uint32_t(Compile2.getFlags()), |
929 | getCompileSym3FlagNames()); |
930 | W.printEnum("Machine" , unsigned(Compile2.Machine), getCPUTypeNames()); |
931 | W.printString("VersionName" , Compile2.Version); |
932 | }); |
933 | |
934 | // MSVC generates the following sequence for a CodeView module: |
935 | // S_OBJNAME --> Set 'CurrentObjectName'. |
936 | // S_COMPILE2 --> Set the compile unit name using 'CurrentObjectName'. |
937 | // ... |
938 | // S_BUILDINFO --> Extract the source name. |
939 | // |
940 | // Clang generates the following sequence for a CodeView module: |
941 | // S_COMPILE2 --> Set the compile unit name to empty string. |
942 | // ... |
943 | // S_BUILDINFO --> Extract the source name. |
944 | // |
945 | // For both toolchains, update the compile unit name from S_BUILDINFO. |
946 | if (LVScope *Scope = LogicalVisitor->CurrentScope) { |
947 | // The name of the CU, was extracted from the 'BuildInfo' subsection. |
948 | Reader->setCompileUnitCPUType(Compile2.Machine); |
949 | Scope->setName(CurrentObjectName); |
950 | if (options().getAttributeProducer()) |
951 | Scope->setProducer(Compile2.Version); |
952 | if (options().getAttributeLanguage()) |
953 | Scope->setSourceLanguage(LVSourceLanguage{ |
954 | static_cast<llvm::codeview::SourceLanguage>(Compile2.getLanguage())}); |
955 | getReader().isSystemEntry(Element: Scope, Name: CurrentObjectName); |
956 | |
957 | // The line records in CodeView are recorded per Module ID. Update |
958 | // the relationship between the current CU and the Module ID. |
959 | Reader->addModule(Scope); |
960 | |
961 | // Updated the collected strings with their associated compile unit. |
962 | Shared->StringRecords.addFilenames(Scope: Reader->getCompileUnit()); |
963 | } |
964 | |
965 | // Clear any previous ObjectName. |
966 | CurrentObjectName = "" ; |
967 | return Error::success(); |
968 | } |
969 | |
970 | // S_COMPILE3 |
971 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
972 | Compile3Sym &Compile3) { |
973 | LLVM_DEBUG({ |
974 | W.printEnum("Language" , uint8_t(Compile3.getLanguage()), |
975 | getSourceLanguageNames()); |
976 | W.printFlags("Flags" , uint32_t(Compile3.getFlags()), |
977 | getCompileSym3FlagNames()); |
978 | W.printEnum("Machine" , unsigned(Compile3.Machine), getCPUTypeNames()); |
979 | W.printString("VersionName" , Compile3.Version); |
980 | }); |
981 | |
982 | // MSVC generates the following sequence for a CodeView module: |
983 | // S_OBJNAME --> Set 'CurrentObjectName'. |
984 | // S_COMPILE3 --> Set the compile unit name using 'CurrentObjectName'. |
985 | // ... |
986 | // S_BUILDINFO --> Extract the source name. |
987 | // |
988 | // Clang generates the following sequence for a CodeView module: |
989 | // S_COMPILE3 --> Set the compile unit name to empty string. |
990 | // ... |
991 | // S_BUILDINFO --> Extract the source name. |
992 | // |
993 | // For both toolchains, update the compile unit name from S_BUILDINFO. |
994 | if (LVScope *Scope = LogicalVisitor->CurrentScope) { |
995 | // The name of the CU, was extracted from the 'BuildInfo' subsection. |
996 | Reader->setCompileUnitCPUType(Compile3.Machine); |
997 | Scope->setName(CurrentObjectName); |
998 | if (options().getAttributeProducer()) |
999 | Scope->setProducer(Compile3.Version); |
1000 | if (options().getAttributeLanguage()) |
1001 | Scope->setSourceLanguage(LVSourceLanguage{ |
1002 | static_cast<llvm::codeview::SourceLanguage>(Compile3.getLanguage())}); |
1003 | getReader().isSystemEntry(Element: Scope, Name: CurrentObjectName); |
1004 | |
1005 | // The line records in CodeView are recorded per Module ID. Update |
1006 | // the relationship between the current CU and the Module ID. |
1007 | Reader->addModule(Scope); |
1008 | |
1009 | // Updated the collected strings with their associated compile unit. |
1010 | Shared->StringRecords.addFilenames(Scope: Reader->getCompileUnit()); |
1011 | } |
1012 | |
1013 | // Clear any previous ObjectName. |
1014 | CurrentObjectName = "" ; |
1015 | return Error::success(); |
1016 | } |
1017 | |
1018 | // S_CONSTANT, S_MANCONSTANT |
1019 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
1020 | ConstantSym &Constant) { |
1021 | LLVM_DEBUG({ |
1022 | printTypeIndex("Type" , Constant.Type); |
1023 | W.printNumber("Value" , Constant.Value); |
1024 | W.printString("Name" , Constant.Name); |
1025 | }); |
1026 | |
1027 | if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { |
1028 | Symbol->setName(Constant.Name); |
1029 | Symbol->setType(LogicalVisitor->getElement(StreamIdx: StreamTPI, TI: Constant.Type)); |
1030 | Symbol->resetIncludeInPrint(); |
1031 | } |
1032 | |
1033 | return Error::success(); |
1034 | } |
1035 | |
1036 | // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE |
1037 | Error LVSymbolVisitor::visitKnownRecord( |
1038 | CVSymbol &Record, |
1039 | DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { |
1040 | // DefRanges don't have types, just registers and code offsets. |
1041 | LLVM_DEBUG({ |
1042 | if (LocalSymbol) |
1043 | W.getOStream() << formatv("Symbol: {0}, " , LocalSymbol->getName()); |
1044 | |
1045 | W.printNumber("Offset" , DefRangeFramePointerRelFullScope.Offset); |
1046 | }); |
1047 | |
1048 | if (LVSymbol *Symbol = LocalSymbol) { |
1049 | Symbol->setHasCodeViewLocation(); |
1050 | LocalSymbol = nullptr; |
1051 | |
1052 | // Add location debug location. Operands: [Offset, 0]. |
1053 | dwarf::Attribute Attr = |
1054 | dwarf::Attribute(SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE); |
1055 | |
1056 | uint64_t Operand1 = DefRangeFramePointerRelFullScope.Offset; |
1057 | Symbol->addLocation(Attr, LowPC: 0, HighPC: 0, SectionOffset: 0, LocDescOffset: 0); |
1058 | Symbol->addLocationOperands(Opcode: LVSmall(Attr), Operands: {Operand1}); |
1059 | } |
1060 | |
1061 | return Error::success(); |
1062 | } |
1063 | |
1064 | // S_DEFRANGE_FRAMEPOINTER_REL |
1065 | Error LVSymbolVisitor::visitKnownRecord( |
1066 | CVSymbol &Record, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { |
1067 | // DefRanges don't have types, just registers and code offsets. |
1068 | LLVM_DEBUG({ |
1069 | if (LocalSymbol) |
1070 | W.getOStream() << formatv("Symbol: {0}, " , LocalSymbol->getName()); |
1071 | |
1072 | W.printNumber("Offset" , DefRangeFramePointerRel.Hdr.Offset); |
1073 | printLocalVariableAddrRange(DefRangeFramePointerRel.Range, |
1074 | DefRangeFramePointerRel.getRelocationOffset()); |
1075 | printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); |
1076 | }); |
1077 | |
1078 | // We are expecting the following sequence: |
1079 | // 128 | S_LOCAL [size = 20] `ParamBar` |
1080 | // ... |
1081 | // 148 | S_DEFRANGE_FRAMEPOINTER_REL [size = 16] |
1082 | if (LVSymbol *Symbol = LocalSymbol) { |
1083 | Symbol->setHasCodeViewLocation(); |
1084 | LocalSymbol = nullptr; |
1085 | |
1086 | // Add location debug location. Operands: [Offset, 0]. |
1087 | dwarf::Attribute Attr = |
1088 | dwarf::Attribute(SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL); |
1089 | uint64_t Operand1 = DefRangeFramePointerRel.Hdr.Offset; |
1090 | |
1091 | LocalVariableAddrRange Range = DefRangeFramePointerRel.Range; |
1092 | LVAddress Address = |
1093 | Reader->linearAddress(Segment: Range.ISectStart, Offset: Range.OffsetStart); |
1094 | |
1095 | Symbol->addLocation(Attr, LowPC: Address, HighPC: Address + Range.Range, SectionOffset: 0, LocDescOffset: 0); |
1096 | Symbol->addLocationOperands(Opcode: LVSmall(Attr), Operands: {Operand1}); |
1097 | } |
1098 | |
1099 | return Error::success(); |
1100 | } |
1101 | |
1102 | // S_DEFRANGE_REGISTER_REL |
1103 | Error LVSymbolVisitor::visitKnownRecord( |
1104 | CVSymbol &Record, DefRangeRegisterRelSym &DefRangeRegisterRel) { |
1105 | // DefRanges don't have types, just registers and code offsets. |
1106 | LLVM_DEBUG({ |
1107 | if (LocalSymbol) |
1108 | W.getOStream() << formatv("Symbol: {0}, " , LocalSymbol->getName()); |
1109 | |
1110 | W.printBoolean("HasSpilledUDTMember" , |
1111 | DefRangeRegisterRel.hasSpilledUDTMember()); |
1112 | W.printNumber("OffsetInParent" , DefRangeRegisterRel.offsetInParent()); |
1113 | W.printNumber("BasePointerOffset" , |
1114 | DefRangeRegisterRel.Hdr.BasePointerOffset); |
1115 | printLocalVariableAddrRange(DefRangeRegisterRel.Range, |
1116 | DefRangeRegisterRel.getRelocationOffset()); |
1117 | printLocalVariableAddrGap(DefRangeRegisterRel.Gaps); |
1118 | }); |
1119 | |
1120 | if (LVSymbol *Symbol = LocalSymbol) { |
1121 | Symbol->setHasCodeViewLocation(); |
1122 | LocalSymbol = nullptr; |
1123 | |
1124 | // Add location debug location. Operands: [Register, Offset]. |
1125 | dwarf::Attribute Attr = |
1126 | dwarf::Attribute(SymbolKind::S_DEFRANGE_REGISTER_REL); |
1127 | uint64_t Operand1 = DefRangeRegisterRel.Hdr.Register; |
1128 | uint64_t Operand2 = DefRangeRegisterRel.Hdr.BasePointerOffset; |
1129 | |
1130 | LocalVariableAddrRange Range = DefRangeRegisterRel.Range; |
1131 | LVAddress Address = |
1132 | Reader->linearAddress(Segment: Range.ISectStart, Offset: Range.OffsetStart); |
1133 | |
1134 | Symbol->addLocation(Attr, LowPC: Address, HighPC: Address + Range.Range, SectionOffset: 0, LocDescOffset: 0); |
1135 | Symbol->addLocationOperands(Opcode: LVSmall(Attr), Operands: {Operand1, Operand2}); |
1136 | } |
1137 | |
1138 | return Error::success(); |
1139 | } |
1140 | |
1141 | // S_DEFRANGE_REGISTER |
1142 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
1143 | DefRangeRegisterSym &DefRangeRegister) { |
1144 | // DefRanges don't have types, just registers and code offsets. |
1145 | LLVM_DEBUG({ |
1146 | if (LocalSymbol) |
1147 | W.getOStream() << formatv("Symbol: {0}, " , LocalSymbol->getName()); |
1148 | |
1149 | W.printEnum("Register" , uint16_t(DefRangeRegister.Hdr.Register), |
1150 | getRegisterNames(Reader->getCompileUnitCPUType())); |
1151 | W.printNumber("MayHaveNoName" , DefRangeRegister.Hdr.MayHaveNoName); |
1152 | printLocalVariableAddrRange(DefRangeRegister.Range, |
1153 | DefRangeRegister.getRelocationOffset()); |
1154 | printLocalVariableAddrGap(DefRangeRegister.Gaps); |
1155 | }); |
1156 | |
1157 | if (LVSymbol *Symbol = LocalSymbol) { |
1158 | Symbol->setHasCodeViewLocation(); |
1159 | LocalSymbol = nullptr; |
1160 | |
1161 | // Add location debug location. Operands: [Register, 0]. |
1162 | dwarf::Attribute Attr = dwarf::Attribute(SymbolKind::S_DEFRANGE_REGISTER); |
1163 | uint64_t Operand1 = DefRangeRegister.Hdr.Register; |
1164 | |
1165 | LocalVariableAddrRange Range = DefRangeRegister.Range; |
1166 | LVAddress Address = |
1167 | Reader->linearAddress(Segment: Range.ISectStart, Offset: Range.OffsetStart); |
1168 | |
1169 | Symbol->addLocation(Attr, LowPC: Address, HighPC: Address + Range.Range, SectionOffset: 0, LocDescOffset: 0); |
1170 | Symbol->addLocationOperands(Opcode: LVSmall(Attr), Operands: {Operand1}); |
1171 | } |
1172 | |
1173 | return Error::success(); |
1174 | } |
1175 | |
1176 | // S_DEFRANGE_SUBFIELD_REGISTER |
1177 | Error LVSymbolVisitor::visitKnownRecord( |
1178 | CVSymbol &Record, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) { |
1179 | // DefRanges don't have types, just registers and code offsets. |
1180 | LLVM_DEBUG({ |
1181 | if (LocalSymbol) |
1182 | W.getOStream() << formatv("Symbol: {0}, " , LocalSymbol->getName()); |
1183 | |
1184 | W.printEnum("Register" , uint16_t(DefRangeSubfieldRegister.Hdr.Register), |
1185 | getRegisterNames(Reader->getCompileUnitCPUType())); |
1186 | W.printNumber("MayHaveNoName" , DefRangeSubfieldRegister.Hdr.MayHaveNoName); |
1187 | W.printNumber("OffsetInParent" , |
1188 | DefRangeSubfieldRegister.Hdr.OffsetInParent); |
1189 | printLocalVariableAddrRange(DefRangeSubfieldRegister.Range, |
1190 | DefRangeSubfieldRegister.getRelocationOffset()); |
1191 | printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps); |
1192 | }); |
1193 | |
1194 | if (LVSymbol *Symbol = LocalSymbol) { |
1195 | Symbol->setHasCodeViewLocation(); |
1196 | LocalSymbol = nullptr; |
1197 | |
1198 | // Add location debug location. Operands: [Register, 0]. |
1199 | dwarf::Attribute Attr = |
1200 | dwarf::Attribute(SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER); |
1201 | uint64_t Operand1 = DefRangeSubfieldRegister.Hdr.Register; |
1202 | |
1203 | LocalVariableAddrRange Range = DefRangeSubfieldRegister.Range; |
1204 | LVAddress Address = |
1205 | Reader->linearAddress(Segment: Range.ISectStart, Offset: Range.OffsetStart); |
1206 | |
1207 | Symbol->addLocation(Attr, LowPC: Address, HighPC: Address + Range.Range, SectionOffset: 0, LocDescOffset: 0); |
1208 | Symbol->addLocationOperands(Opcode: LVSmall(Attr), Operands: {Operand1}); |
1209 | } |
1210 | |
1211 | return Error::success(); |
1212 | } |
1213 | |
1214 | // S_DEFRANGE_SUBFIELD |
1215 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
1216 | DefRangeSubfieldSym &DefRangeSubfield) { |
1217 | // DefRanges don't have types, just registers and code offsets. |
1218 | LLVM_DEBUG({ |
1219 | if (LocalSymbol) |
1220 | W.getOStream() << formatv("Symbol: {0}, " , LocalSymbol->getName()); |
1221 | |
1222 | if (ObjDelegate) { |
1223 | DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); |
1224 | auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program); |
1225 | if (!ExpectedProgram) { |
1226 | consumeError(ExpectedProgram.takeError()); |
1227 | return llvm::make_error<CodeViewError>( |
1228 | "String table offset outside of bounds of String Table!" ); |
1229 | } |
1230 | W.printString("Program" , *ExpectedProgram); |
1231 | } |
1232 | W.printNumber("OffsetInParent" , DefRangeSubfield.OffsetInParent); |
1233 | printLocalVariableAddrRange(DefRangeSubfield.Range, |
1234 | DefRangeSubfield.getRelocationOffset()); |
1235 | printLocalVariableAddrGap(DefRangeSubfield.Gaps); |
1236 | }); |
1237 | |
1238 | if (LVSymbol *Symbol = LocalSymbol) { |
1239 | Symbol->setHasCodeViewLocation(); |
1240 | LocalSymbol = nullptr; |
1241 | |
1242 | // Add location debug location. Operands: [Program, 0]. |
1243 | dwarf::Attribute Attr = dwarf::Attribute(SymbolKind::S_DEFRANGE_SUBFIELD); |
1244 | uint64_t Operand1 = DefRangeSubfield.Program; |
1245 | |
1246 | LocalVariableAddrRange Range = DefRangeSubfield.Range; |
1247 | LVAddress Address = |
1248 | Reader->linearAddress(Segment: Range.ISectStart, Offset: Range.OffsetStart); |
1249 | |
1250 | Symbol->addLocation(Attr, LowPC: Address, HighPC: Address + Range.Range, SectionOffset: 0, LocDescOffset: 0); |
1251 | Symbol->addLocationOperands(Opcode: LVSmall(Attr), Operands: {Operand1, /*Operand2=*/0}); |
1252 | } |
1253 | |
1254 | return Error::success(); |
1255 | } |
1256 | |
1257 | // S_DEFRANGE |
1258 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
1259 | DefRangeSym &DefRange) { |
1260 | // DefRanges don't have types, just registers and code offsets. |
1261 | LLVM_DEBUG({ |
1262 | if (LocalSymbol) |
1263 | W.getOStream() << formatv("Symbol: {0}, " , LocalSymbol->getName()); |
1264 | |
1265 | if (ObjDelegate) { |
1266 | DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); |
1267 | auto ExpectedProgram = Strings.getString(DefRange.Program); |
1268 | if (!ExpectedProgram) { |
1269 | consumeError(ExpectedProgram.takeError()); |
1270 | return llvm::make_error<CodeViewError>( |
1271 | "String table offset outside of bounds of String Table!" ); |
1272 | } |
1273 | W.printString("Program" , *ExpectedProgram); |
1274 | } |
1275 | printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset()); |
1276 | printLocalVariableAddrGap(DefRange.Gaps); |
1277 | }); |
1278 | |
1279 | if (LVSymbol *Symbol = LocalSymbol) { |
1280 | Symbol->setHasCodeViewLocation(); |
1281 | LocalSymbol = nullptr; |
1282 | |
1283 | // Add location debug location. Operands: [Program, 0]. |
1284 | dwarf::Attribute Attr = dwarf::Attribute(SymbolKind::S_DEFRANGE); |
1285 | uint64_t Operand1 = DefRange.Program; |
1286 | |
1287 | LocalVariableAddrRange Range = DefRange.Range; |
1288 | LVAddress Address = |
1289 | Reader->linearAddress(Segment: Range.ISectStart, Offset: Range.OffsetStart); |
1290 | |
1291 | Symbol->addLocation(Attr, LowPC: Address, HighPC: Address + Range.Range, SectionOffset: 0, LocDescOffset: 0); |
1292 | Symbol->addLocationOperands(Opcode: LVSmall(Attr), Operands: {Operand1, /*Operand2=*/0}); |
1293 | } |
1294 | |
1295 | return Error::success(); |
1296 | } |
1297 | |
1298 | // S_FRAMEPROC |
1299 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
1300 | FrameProcSym &FrameProc) { |
1301 | if (LVScope *Function = LogicalVisitor->getReaderScope()) { |
1302 | // S_FRAMEPROC contains extra information for the function described |
1303 | // by any of the previous generated records: |
1304 | // S_GPROC32, S_LPROC32, S_LPROC32_ID, S_GPROC32_ID. |
1305 | |
1306 | // The generated sequence is: |
1307 | // S_GPROC32_ID ... |
1308 | // S_FRAMEPROC ... |
1309 | |
1310 | // Collect additional inline flags for the current scope function. |
1311 | FrameProcedureOptions Flags = FrameProc.Flags; |
1312 | if (FrameProcedureOptions::MarkedInline == |
1313 | (Flags & FrameProcedureOptions::MarkedInline)) |
1314 | Function->setInlineCode(dwarf::DW_INL_declared_inlined); |
1315 | if (FrameProcedureOptions::Inlined == |
1316 | (Flags & FrameProcedureOptions::Inlined)) |
1317 | Function->setInlineCode(dwarf::DW_INL_inlined); |
1318 | |
1319 | // To determine the symbol kind for any symbol declared in that function, |
1320 | // we can access the S_FRAMEPROC for the parent scope function. It contains |
1321 | // information about the local fp and param fp registers and compare with |
1322 | // the register in the S_REGREL32 to get a match. |
1323 | codeview::CPUType CPU = Reader->getCompileUnitCPUType(); |
1324 | LocalFrameRegister = FrameProc.getLocalFramePtrReg(CPU); |
1325 | ParamFrameRegister = FrameProc.getParamFramePtrReg(CPU); |
1326 | } |
1327 | |
1328 | return Error::success(); |
1329 | } |
1330 | |
1331 | // S_GDATA32, S_LDATA32, S_LMANDATA, S_GMANDATA |
1332 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, DataSym &Data) { |
1333 | LLVM_DEBUG({ |
1334 | printTypeIndex("Type" , Data.Type); |
1335 | W.printString("DisplayName" , Data.Name); |
1336 | }); |
1337 | |
1338 | if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { |
1339 | StringRef LinkageName; |
1340 | if (ObjDelegate) |
1341 | ObjDelegate->getLinkageName(RelocOffset: Data.getRelocationOffset(), Offset: Data.DataOffset, |
1342 | RelocSym: &LinkageName); |
1343 | |
1344 | Symbol->setName(Data.Name); |
1345 | Symbol->setLinkageName(LinkageName); |
1346 | |
1347 | // The MSVC generates local data as initialization for aggregates. It |
1348 | // contains the address for an initialization function. |
1349 | // The symbols contains the '$initializer$' pattern. Allow them only if |
1350 | // the '--internal=system' option is given. |
1351 | // 0 | S_LDATA32 `Struct$initializer$` |
1352 | // type = 0x1040 (void ()*) |
1353 | if (getReader().isSystemEntry(Element: Symbol) && !options().getAttributeSystem()) { |
1354 | Symbol->resetIncludeInPrint(); |
1355 | return Error::success(); |
1356 | } |
1357 | |
1358 | if (LVScope *Namespace = Shared->NamespaceDeduction.get(ScopedName: Data.Name)) { |
1359 | // The variable is already at different scope. In order to reflect |
1360 | // the correct parent, move it to the namespace. |
1361 | if (Symbol->getParentScope()->removeElement(Element: Symbol)) |
1362 | Namespace->addElement(Symbol); |
1363 | } |
1364 | |
1365 | Symbol->setType(LogicalVisitor->getElement(StreamIdx: StreamTPI, TI: Data.Type)); |
1366 | if (Record.kind() == SymbolKind::S_GDATA32) |
1367 | Symbol->setIsExternal(); |
1368 | } |
1369 | |
1370 | return Error::success(); |
1371 | } |
1372 | |
1373 | // S_INLINESITE |
1374 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
1375 | InlineSiteSym &InlineSite) { |
1376 | LLVM_DEBUG({ printTypeIndex("Inlinee" , InlineSite.Inlinee); }); |
1377 | |
1378 | if (LVScope *InlinedFunction = LogicalVisitor->CurrentScope) { |
1379 | LVScope *AbstractFunction = Reader->createScopeFunction(); |
1380 | AbstractFunction->setIsSubprogram(); |
1381 | AbstractFunction->setTag(dwarf::DW_TAG_subprogram); |
1382 | AbstractFunction->setInlineCode(dwarf::DW_INL_inlined); |
1383 | AbstractFunction->setIsInlinedAbstract(); |
1384 | InlinedFunction->setReference(AbstractFunction); |
1385 | |
1386 | LogicalVisitor->startProcessArgumentList(); |
1387 | // 'Inlinee' is a Type ID. |
1388 | CVType CVFunctionType = Ids.getType(Index: InlineSite.Inlinee); |
1389 | if (Error Err = LogicalVisitor->finishVisitation( |
1390 | Record&: CVFunctionType, TI: InlineSite.Inlinee, Element: AbstractFunction)) |
1391 | return Err; |
1392 | LogicalVisitor->stopProcessArgumentList(); |
1393 | |
1394 | // For inlined functions set the linkage name to be the same as |
1395 | // the name. It used to find their lines and ranges. |
1396 | StringRef Name = AbstractFunction->getName(); |
1397 | InlinedFunction->setName(Name); |
1398 | InlinedFunction->setLinkageName(Name); |
1399 | |
1400 | // Process annotation bytes to calculate code and line offsets. |
1401 | if (Error Err = LogicalVisitor->inlineSiteAnnotation( |
1402 | AbstractFunction, InlinedFunction, InlineSite)) |
1403 | return Err; |
1404 | } |
1405 | |
1406 | return Error::success(); |
1407 | } |
1408 | |
1409 | // S_LOCAL |
1410 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, LocalSym &Local) { |
1411 | LLVM_DEBUG({ |
1412 | printTypeIndex("Type" , Local.Type); |
1413 | W.printFlags("Flags" , uint16_t(Local.Flags), getLocalFlagNames()); |
1414 | W.printString("VarName" , Local.Name); |
1415 | }); |
1416 | |
1417 | if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { |
1418 | Symbol->setName(Local.Name); |
1419 | |
1420 | // Symbol was created as 'variable'; determine its real kind. |
1421 | Symbol->resetIsVariable(); |
1422 | |
1423 | // Be sure the 'this' symbol is marked as 'compiler generated'. |
1424 | if (bool(Local.Flags & LocalSymFlags::IsCompilerGenerated) || |
1425 | Local.Name == "this" ) { |
1426 | Symbol->setIsArtificial(); |
1427 | Symbol->setIsParameter(); |
1428 | } else { |
1429 | bool(Local.Flags & LocalSymFlags::IsParameter) ? Symbol->setIsParameter() |
1430 | : Symbol->setIsVariable(); |
1431 | } |
1432 | |
1433 | // Update correct debug information tag. |
1434 | if (Symbol->getIsParameter()) |
1435 | Symbol->setTag(dwarf::DW_TAG_formal_parameter); |
1436 | |
1437 | LVElement *Element = LogicalVisitor->getElement(StreamIdx: StreamTPI, TI: Local.Type); |
1438 | if (Element && Element->getIsScoped()) { |
1439 | // We have a local type. Find its parent function. |
1440 | LVScope *Parent = Symbol->getFunctionParent(); |
1441 | // The element representing the type has been already finalized. If |
1442 | // the type is an aggregate type, its members have been already added. |
1443 | // As the type is local, its level will be changed. |
1444 | Parent->addElement(Element); |
1445 | Element->updateLevel(Parent); |
1446 | } |
1447 | Symbol->setType(Element); |
1448 | |
1449 | // The CodeView records (S_DEFFRAME_*) describing debug location for |
1450 | // this symbol, do not have any direct reference to it. Those records |
1451 | // are emitted after this symbol. Record the current symbol. |
1452 | LocalSymbol = Symbol; |
1453 | } |
1454 | |
1455 | return Error::success(); |
1456 | } |
1457 | |
1458 | // S_OBJNAME |
1459 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, ObjNameSym &ObjName) { |
1460 | LLVM_DEBUG({ |
1461 | W.printHex("Signature" , ObjName.Signature); |
1462 | W.printString("ObjectName" , ObjName.Name); |
1463 | }); |
1464 | |
1465 | CurrentObjectName = ObjName.Name; |
1466 | return Error::success(); |
1467 | } |
1468 | |
1469 | // S_GPROC32, S_LPROC32, S_LPROC32_ID, S_GPROC32_ID |
1470 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, ProcSym &Proc) { |
1471 | if (InFunctionScope) |
1472 | return llvm::make_error<CodeViewError>(Args: "Visiting a ProcSym while inside " |
1473 | "function scope!" ); |
1474 | |
1475 | InFunctionScope = true; |
1476 | |
1477 | LLVM_DEBUG({ |
1478 | printTypeIndex("FunctionType" , Proc.FunctionType); |
1479 | W.printHex("Segment" , Proc.Segment); |
1480 | W.printFlags("Flags" , static_cast<uint8_t>(Proc.Flags), |
1481 | getProcSymFlagNames()); |
1482 | W.printString("DisplayName" , Proc.Name); |
1483 | }); |
1484 | |
1485 | // Clang and Microsoft generated different debug information records: |
1486 | // For functions definitions: |
1487 | // Clang: S_GPROC32 -> LF_FUNC_ID -> LF_PROCEDURE |
1488 | // Microsoft: S_GPROC32 -> LF_PROCEDURE |
1489 | |
1490 | // For member function definition: |
1491 | // Clang: S_GPROC32 -> LF_MFUNC_ID -> LF_MFUNCTION |
1492 | // Microsoft: S_GPROC32 -> LF_MFUNCTION |
1493 | // In order to support both sequences, if we found LF_FUNCTION_ID, just |
1494 | // get the TypeIndex for LF_PROCEDURE. |
1495 | |
1496 | // For the given test case, we have the sequence: |
1497 | // namespace NSP_local { |
1498 | // void foo_local() { |
1499 | // } |
1500 | // } |
1501 | // |
1502 | // 0x1000 | LF_STRING_ID String: NSP_local |
1503 | // 0x1002 | LF_PROCEDURE |
1504 | // return type = 0x0003 (void), # args = 0, param list = 0x1001 |
1505 | // calling conv = cdecl, options = None |
1506 | // 0x1003 | LF_FUNC_ID |
1507 | // name = foo_local, type = 0x1002, parent scope = 0x1000 |
1508 | // 0 | S_GPROC32_ID `NSP_local::foo_local` |
1509 | // type = `0x1003 (foo_local)` |
1510 | // 0x1004 | LF_STRING_ID String: suite |
1511 | // 0x1005 | LF_STRING_ID String: suite_local.cpp |
1512 | // |
1513 | // The LF_STRING_ID can hold different information: |
1514 | // 0x1000 - The enclosing namespace. |
1515 | // 0x1004 - The compile unit directory name. |
1516 | // 0x1005 - The compile unit name. |
1517 | // |
1518 | // Before deducting its scope, we need to evaluate its type and create any |
1519 | // associated namespaces. |
1520 | if (LVScope *Function = LogicalVisitor->CurrentScope) { |
1521 | StringRef LinkageName; |
1522 | if (ObjDelegate) |
1523 | ObjDelegate->getLinkageName(RelocOffset: Proc.getRelocationOffset(), Offset: Proc.CodeOffset, |
1524 | RelocSym: &LinkageName); |
1525 | |
1526 | // The line table can be accessed using the linkage name. |
1527 | Reader->addToSymbolTable(Name: LinkageName, Function); |
1528 | Function->setName(Proc.Name); |
1529 | Function->setLinkageName(LinkageName); |
1530 | |
1531 | if (options().getGeneralCollectRanges()) { |
1532 | // Record converted segment::offset addressing for this scope. |
1533 | LVAddress Addendum = Reader->getSymbolTableAddress(Name: LinkageName); |
1534 | LVAddress LowPC = |
1535 | Reader->linearAddress(Segment: Proc.Segment, Offset: Proc.CodeOffset, Addendum); |
1536 | LVAddress HighPC = LowPC + Proc.CodeSize - 1; |
1537 | Function->addObject(LowerAddress: LowPC, UpperAddress: HighPC); |
1538 | |
1539 | // If the scope is a function, add it to the public names. |
1540 | if ((options().getAttributePublics() || options().getPrintAnyLine()) && |
1541 | !Function->getIsInlinedFunction()) |
1542 | Reader->getCompileUnit()->addPublicName(Scope: Function, LowPC, HighPC); |
1543 | } |
1544 | |
1545 | if (Function->getIsSystem() && !options().getAttributeSystem()) { |
1546 | Function->resetIncludeInPrint(); |
1547 | return Error::success(); |
1548 | } |
1549 | |
1550 | TypeIndex TIFunctionType = Proc.FunctionType; |
1551 | if (TIFunctionType.isSimple()) |
1552 | Function->setType(LogicalVisitor->getElement(StreamIdx: StreamTPI, TI: TIFunctionType)); |
1553 | else { |
1554 | // We have to detect the correct stream, using the lexical parent |
1555 | // name, as there is not other obvious way to get the stream. |
1556 | // Normal function: LF_FUNC_ID (TPI)/(IPI) |
1557 | // LF_PROCEDURE (TPI) |
1558 | // Lambda function: LF_MFUNCTION (TPI) |
1559 | // Member function: LF_MFUNC_ID (TPI)/(IPI) |
1560 | |
1561 | StringRef OuterComponent; |
1562 | std::tie(args&: OuterComponent, args: std::ignore) = getInnerComponent(Name: Proc.Name); |
1563 | TypeIndex TI = Shared->ForwardReferences.find(Name: OuterComponent); |
1564 | |
1565 | std::optional<CVType> CVFunctionType; |
1566 | auto GetRecordType = [&]() -> bool { |
1567 | CVFunctionType = Ids.tryGetType(Index: TIFunctionType); |
1568 | if (!CVFunctionType) |
1569 | return false; |
1570 | |
1571 | if (TI.isNoneType()) |
1572 | // Normal function. |
1573 | if (CVFunctionType->kind() == LF_FUNC_ID) |
1574 | return true; |
1575 | |
1576 | // Member function. |
1577 | return (CVFunctionType->kind() == LF_MFUNC_ID); |
1578 | }; |
1579 | |
1580 | // We can have a LF_FUNC_ID, LF_PROCEDURE or LF_MFUNCTION. |
1581 | if (!GetRecordType()) { |
1582 | CVFunctionType = Types.tryGetType(Index: TIFunctionType); |
1583 | if (!CVFunctionType) |
1584 | return llvm::make_error<CodeViewError>(Args: "Invalid type index" ); |
1585 | } |
1586 | |
1587 | if (Error Err = LogicalVisitor->finishVisitation( |
1588 | Record&: *CVFunctionType, TI: TIFunctionType, Element: Function)) |
1589 | return Err; |
1590 | } |
1591 | |
1592 | if (Record.kind() == SymbolKind::S_GPROC32 || |
1593 | Record.kind() == SymbolKind::S_GPROC32_ID) |
1594 | Function->setIsExternal(); |
1595 | |
1596 | // We don't have a way to see if the symbol is compiler generated. Use |
1597 | // the linkage name, to detect `scalar deleting destructor' functions. |
1598 | std::string DemangledSymbol = demangle(MangledName: LinkageName); |
1599 | if (DemangledSymbol.find(s: "scalar deleting dtor" ) != std::string::npos) { |
1600 | Function->setIsArtificial(); |
1601 | } else { |
1602 | // Clang generates global ctor and dtor names containing the substrings: |
1603 | // 'dynamic initializer for' and 'dynamic atexit destructor for'. |
1604 | if (DemangledSymbol.find(s: "dynamic atexit destructor for" ) != |
1605 | std::string::npos) |
1606 | Function->setIsArtificial(); |
1607 | } |
1608 | } |
1609 | |
1610 | return Error::success(); |
1611 | } |
1612 | |
1613 | // S_END |
1614 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
1615 | ScopeEndSym &ScopeEnd) { |
1616 | InFunctionScope = false; |
1617 | return Error::success(); |
1618 | } |
1619 | |
1620 | // S_THUNK32 |
1621 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, Thunk32Sym &Thunk) { |
1622 | if (InFunctionScope) |
1623 | return llvm::make_error<CodeViewError>(Args: "Visiting a Thunk32Sym while inside " |
1624 | "function scope!" ); |
1625 | |
1626 | InFunctionScope = true; |
1627 | |
1628 | LLVM_DEBUG({ |
1629 | W.printHex("Segment" , Thunk.Segment); |
1630 | W.printString("Name" , Thunk.Name); |
1631 | }); |
1632 | |
1633 | if (LVScope *Function = LogicalVisitor->CurrentScope) |
1634 | Function->setName(Thunk.Name); |
1635 | |
1636 | return Error::success(); |
1637 | } |
1638 | |
1639 | // S_UDT, S_COBOLUDT |
1640 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, UDTSym &UDT) { |
1641 | LLVM_DEBUG({ |
1642 | printTypeIndex("Type" , UDT.Type); |
1643 | W.printString("UDTName" , UDT.Name); |
1644 | }); |
1645 | |
1646 | if (LVType *Type = LogicalVisitor->CurrentType) { |
1647 | if (LVScope *Namespace = Shared->NamespaceDeduction.get(ScopedName: UDT.Name)) { |
1648 | if (Type->getParentScope()->removeElement(Element: Type)) |
1649 | Namespace->addElement(Type); |
1650 | } |
1651 | |
1652 | Type->setName(UDT.Name); |
1653 | |
1654 | // We have to determine if the typedef is a real C/C++ definition or is |
1655 | // the S_UDT record that describe all the user defined types. |
1656 | // 0 | S_UDT `Name` original type = 0x1009 |
1657 | // 0x1009 | LF_STRUCTURE `Name` |
1658 | // Ignore type definitions for RTTI types: |
1659 | // _s__RTTIBaseClassArray, _s__RTTIBaseClassDescriptor, |
1660 | // _s__RTTICompleteObjectLocator, _s__RTTIClassHierarchyDescriptor. |
1661 | if (getReader().isSystemEntry(Element: Type)) |
1662 | Type->resetIncludeInPrint(); |
1663 | else { |
1664 | StringRef RecordName = getRecordName(Types, TI: UDT.Type); |
1665 | if (UDT.Name == RecordName) |
1666 | Type->resetIncludeInPrint(); |
1667 | Type->setType(LogicalVisitor->getElement(StreamIdx: StreamTPI, TI: UDT.Type)); |
1668 | } |
1669 | } |
1670 | |
1671 | return Error::success(); |
1672 | } |
1673 | |
1674 | // S_UNAMESPACE |
1675 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, |
1676 | UsingNamespaceSym &UN) { |
1677 | LLVM_DEBUG({ W.printString("Namespace" , UN.Name); }); |
1678 | return Error::success(); |
1679 | } |
1680 | |
1681 | // S_ARMSWITCHTABLE |
1682 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &CVR, |
1683 | JumpTableSym &JumpTable) { |
1684 | LLVM_DEBUG({ |
1685 | W.printHex("BaseOffset" , JumpTable.BaseOffset); |
1686 | W.printNumber("BaseSegment" , JumpTable.BaseSegment); |
1687 | W.printFlags("SwitchType" , static_cast<uint16_t>(JumpTable.SwitchType), |
1688 | getJumpTableEntrySizeNames()); |
1689 | W.printHex("BranchOffset" , JumpTable.BranchOffset); |
1690 | W.printHex("TableOffset" , JumpTable.TableOffset); |
1691 | W.printNumber("BranchSegment" , JumpTable.BranchSegment); |
1692 | W.printNumber("TableSegment" , JumpTable.TableSegment); |
1693 | W.printNumber("EntriesCount" , JumpTable.EntriesCount); |
1694 | }); |
1695 | return Error::success(); |
1696 | } |
1697 | |
1698 | // S_CALLERS, S_CALLEES, S_INLINEES |
1699 | Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, CallerSym &Caller) { |
1700 | LLVM_DEBUG({ |
1701 | llvm::StringRef FieldName; |
1702 | switch (Caller.getKind()) { |
1703 | case SymbolRecordKind::CallerSym: |
1704 | FieldName = "Callee" ; |
1705 | break; |
1706 | case SymbolRecordKind::CalleeSym: |
1707 | FieldName = "Caller" ; |
1708 | break; |
1709 | case SymbolRecordKind::InlineesSym: |
1710 | FieldName = "Inlinee" ; |
1711 | break; |
1712 | default: |
1713 | return llvm::make_error<CodeViewError>( |
1714 | "Unknown CV Record type for a CallerSym object!" ); |
1715 | } |
1716 | for (auto FuncID : Caller.Indices) { |
1717 | printTypeIndex(FieldName, FuncID); |
1718 | } |
1719 | }); |
1720 | return Error::success(); |
1721 | } |
1722 | |
1723 | #undef DEBUG_TYPE |
1724 | #define DEBUG_TYPE "CodeViewLogicalVisitor" |
1725 | |
1726 | //===----------------------------------------------------------------------===// |
1727 | // Logical visitor. |
1728 | //===----------------------------------------------------------------------===// |
1729 | LVLogicalVisitor::LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W, |
1730 | InputFile &Input) |
1731 | : Reader(Reader), W(W), Input(Input) { |
1732 | // The LogicalVisitor connects the CodeViewReader with the visitors that |
1733 | // traverse the types, symbols, etc. Do any initialization that is needed. |
1734 | Shared = std::make_shared<LVShared>(args&: Reader, args: this); |
1735 | } |
1736 | |
1737 | void LVLogicalVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI, |
1738 | uint32_t StreamIdx) { |
1739 | codeview::printTypeIndex(Printer&: W, FieldName, TI, |
1740 | Types&: StreamIdx == StreamTPI ? types() : ids()); |
1741 | } |
1742 | |
1743 | void LVLogicalVisitor::printTypeBegin(CVType &Record, TypeIndex TI, |
1744 | LVElement *Element, uint32_t StreamIdx) { |
1745 | W.getOStream() << "\n" ; |
1746 | W.startLine() << formatTypeLeafKind(K: Record.kind()); |
1747 | W.getOStream() << " (" << HexNumber(TI.getIndex()) << ")" ; |
1748 | W.getOStream() << " {\n" ; |
1749 | W.indent(); |
1750 | W.printEnum(Label: "TypeLeafKind" , Value: unsigned(Record.kind()), EnumValues: ArrayRef(LeafTypeNames)); |
1751 | printTypeIndex(FieldName: "TI" , TI, StreamIdx); |
1752 | W.startLine() << "Element: " << HexNumber(Element->getOffset()) << " " |
1753 | << Element->getName() << "\n" ; |
1754 | } |
1755 | |
1756 | void LVLogicalVisitor::printTypeEnd(CVType &Record) { |
1757 | W.unindent(); |
1758 | W.startLine() << "}\n" ; |
1759 | } |
1760 | |
1761 | void LVLogicalVisitor::printMemberBegin(CVMemberRecord &Record, TypeIndex TI, |
1762 | LVElement *Element, |
1763 | uint32_t StreamIdx) { |
1764 | W.getOStream() << "\n" ; |
1765 | W.startLine() << formatTypeLeafKind(K: Record.Kind); |
1766 | W.getOStream() << " (" << HexNumber(TI.getIndex()) << ")" ; |
1767 | W.getOStream() << " {\n" ; |
1768 | W.indent(); |
1769 | W.printEnum(Label: "TypeLeafKind" , Value: unsigned(Record.Kind), EnumValues: ArrayRef(LeafTypeNames)); |
1770 | printTypeIndex(FieldName: "TI" , TI, StreamIdx); |
1771 | W.startLine() << "Element: " << HexNumber(Element->getOffset()) << " " |
1772 | << Element->getName() << "\n" ; |
1773 | } |
1774 | |
1775 | void LVLogicalVisitor::printMemberEnd(CVMemberRecord &Record) { |
1776 | W.unindent(); |
1777 | W.startLine() << "}\n" ; |
1778 | } |
1779 | |
1780 | Error LVLogicalVisitor::visitUnknownType(CVType &Record, TypeIndex TI) { |
1781 | LLVM_DEBUG({ |
1782 | printTypeIndex("\nTI" , TI, StreamTPI); |
1783 | W.printNumber("Length" , uint32_t(Record.content().size())); |
1784 | }); |
1785 | return Error::success(); |
1786 | } |
1787 | |
1788 | // LF_ARGLIST (TPI) |
1789 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ArgListRecord &Args, |
1790 | TypeIndex TI, LVElement *Element) { |
1791 | ArrayRef<TypeIndex> Indices = Args.getIndices(); |
1792 | uint32_t Size = Indices.size(); |
1793 | LLVM_DEBUG({ |
1794 | printTypeBegin(Record, TI, Element, StreamTPI); |
1795 | W.printNumber("NumArgs" , Size); |
1796 | ListScope Arguments(W, "Arguments" ); |
1797 | for (uint32_t I = 0; I < Size; ++I) |
1798 | printTypeIndex("ArgType" , Indices[I], StreamTPI); |
1799 | printTypeEnd(Record); |
1800 | }); |
1801 | |
1802 | LVScope *Function = static_cast<LVScope *>(Element); |
1803 | for (uint32_t Index = 0; Index < Size; ++Index) { |
1804 | TypeIndex ParameterType = Indices[Index]; |
1805 | createParameter(TI: ParameterType, Name: StringRef(), Parent: Function); |
1806 | } |
1807 | |
1808 | return Error::success(); |
1809 | } |
1810 | |
1811 | // LF_ARRAY (TPI) |
1812 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ArrayRecord &AT, |
1813 | TypeIndex TI, LVElement *Element) { |
1814 | LLVM_DEBUG({ |
1815 | printTypeBegin(Record, TI, Element, StreamTPI); |
1816 | printTypeIndex("ElementType" , AT.getElementType(), StreamTPI); |
1817 | printTypeIndex("IndexType" , AT.getIndexType(), StreamTPI); |
1818 | W.printNumber("SizeOf" , AT.getSize()); |
1819 | W.printString("Name" , AT.getName()); |
1820 | printTypeEnd(Record); |
1821 | }); |
1822 | |
1823 | if (Element->getIsFinalized()) |
1824 | return Error::success(); |
1825 | Element->setIsFinalized(); |
1826 | |
1827 | LVScopeArray *Array = static_cast<LVScopeArray *>(Element); |
1828 | if (!Array) |
1829 | return Error::success(); |
1830 | |
1831 | Reader->getCompileUnit()->addElement(Scope: Array); |
1832 | TypeIndex TIElementType = AT.getElementType(); |
1833 | |
1834 | LVType *PrevSubrange = nullptr; |
1835 | LazyRandomTypeCollection &Types = types(); |
1836 | |
1837 | // As the logical view is modeled on DWARF, for each dimension we have to |
1838 | // create a DW_TAG_subrange_type, with dimension size. |
1839 | // The subrange type can be: unsigned __int32 or unsigned __int64. |
1840 | auto AddSubrangeType = [&](ArrayRecord &AR) { |
1841 | LVType *Subrange = Reader->createTypeSubrange(); |
1842 | Subrange->setTag(dwarf::DW_TAG_subrange_type); |
1843 | Subrange->setType(getElement(StreamIdx: StreamTPI, TI: AR.getIndexType())); |
1844 | Subrange->setCount(AR.getSize()); |
1845 | Subrange->setOffset( |
1846 | TIElementType.isSimple() |
1847 | ? (uint32_t)(TypeLeafKind)TIElementType.getSimpleKind() |
1848 | : TIElementType.getIndex()); |
1849 | Array->addElement(Type: Subrange); |
1850 | |
1851 | if (PrevSubrange) |
1852 | if (int64_t Count = Subrange->getCount()) |
1853 | PrevSubrange->setCount(PrevSubrange->getCount() / Count); |
1854 | PrevSubrange = Subrange; |
1855 | }; |
1856 | |
1857 | // Preserve the original TypeIndex; it would be updated in the case of: |
1858 | // - The array type contains qualifiers. |
1859 | // - In multidimensional arrays, the last LF_ARRAY entry contains the type. |
1860 | TypeIndex TIArrayType; |
1861 | |
1862 | // For each dimension in the array, there is a LF_ARRAY entry. The last |
1863 | // entry contains the array type, which can be a LF_MODIFIER in the case |
1864 | // of the type being modified by a qualifier (const, etc). |
1865 | ArrayRecord AR(AT); |
1866 | CVType CVEntry = Record; |
1867 | while (CVEntry.kind() == LF_ARRAY) { |
1868 | // Create the subrange information, required by the logical view. Once |
1869 | // the array has been processed, the dimension sizes will updated, as |
1870 | // the sizes are a progression. For instance: |
1871 | // sizeof(int) = 4 |
1872 | // int Array[2]; Sizes: 8 Dim: 8 / 4 -> [2] |
1873 | // int Array[2][3]; Sizes: 24, 12 Dim: 24 / 12 -> [2] |
1874 | // Dim: 12 / 4 -> [3] |
1875 | // int Array[2][3][4]; sizes: 96, 48, 16 Dim: 96 / 48 -> [2] |
1876 | // Dim: 48 / 16 -> [3] |
1877 | // Dim: 16 / 4 -> [4] |
1878 | AddSubrangeType(AR); |
1879 | TIArrayType = TIElementType; |
1880 | |
1881 | // The current ElementType can be a modifier, in which case we need to |
1882 | // get the type being modified. |
1883 | // If TypeIndex is not a simple type, check if we have a qualified type. |
1884 | if (!TIElementType.isSimple()) { |
1885 | CVType CVElementType = Types.getType(Index: TIElementType); |
1886 | if (CVElementType.kind() == LF_MODIFIER) { |
1887 | LVElement *QualifiedType = |
1888 | Shared->TypeRecords.find(StreamIdx: StreamTPI, TI: TIElementType); |
1889 | if (Error Err = |
1890 | finishVisitation(Record&: CVElementType, TI: TIElementType, Element: QualifiedType)) |
1891 | return Err; |
1892 | // Get the TypeIndex of the type that the LF_MODIFIER modifies. |
1893 | TIElementType = getModifiedType(CVT: CVElementType); |
1894 | } |
1895 | } |
1896 | // Ends the traversal, as we have reached a simple type (int, char, etc). |
1897 | if (TIElementType.isSimple()) |
1898 | break; |
1899 | |
1900 | // Read next dimension linked entry, if any. |
1901 | CVEntry = Types.getType(Index: TIElementType); |
1902 | if (Error Err = TypeDeserializer::deserializeAs( |
1903 | CVT&: const_cast<CVType &>(CVEntry), Record&: AR)) { |
1904 | consumeError(Err: std::move(Err)); |
1905 | break; |
1906 | } |
1907 | TIElementType = AR.getElementType(); |
1908 | // NOTE: The typeindex has a value of: 0x0280.0000 |
1909 | getTrueType(TI&: TIElementType); |
1910 | } |
1911 | |
1912 | Array->setName(AT.getName()); |
1913 | TIArrayType = Shared->ForwardReferences.remap(TI: TIArrayType); |
1914 | Array->setType(getElement(StreamIdx: StreamTPI, TI: TIArrayType)); |
1915 | |
1916 | if (PrevSubrange) |
1917 | // In the case of an aggregate type (class, struct, union, interface), |
1918 | // get the aggregate size. As the original record is pointing to its |
1919 | // reference, we have to update it. |
1920 | if (uint64_t Size = |
1921 | isAggregate(CVT: CVEntry) |
1922 | ? getSizeInBytesForTypeRecord(CVT: Types.getType(Index: TIArrayType)) |
1923 | : getSizeInBytesForTypeIndex(TI: TIElementType)) |
1924 | PrevSubrange->setCount(PrevSubrange->getCount() / Size); |
1925 | |
1926 | return Error::success(); |
1927 | } |
1928 | |
1929 | // LF_BITFIELD (TPI) |
1930 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, BitFieldRecord &BF, |
1931 | TypeIndex TI, LVElement *Element) { |
1932 | LLVM_DEBUG({ |
1933 | printTypeBegin(Record, TI, Element, StreamTPI); |
1934 | printTypeIndex("Type" , TI, StreamTPI); |
1935 | W.printNumber("BitSize" , BF.getBitSize()); |
1936 | W.printNumber("BitOffset" , BF.getBitOffset()); |
1937 | printTypeEnd(Record); |
1938 | }); |
1939 | |
1940 | Element->setType(getElement(StreamIdx: StreamTPI, TI: BF.getType())); |
1941 | Element->setBitSize(BF.getBitSize()); |
1942 | return Error::success(); |
1943 | } |
1944 | |
1945 | // LF_BUILDINFO (TPI)/(IPI) |
1946 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, BuildInfoRecord &BI, |
1947 | TypeIndex TI, LVElement *Element) { |
1948 | LLVM_DEBUG({ |
1949 | printTypeBegin(Record, TI, Element, StreamIPI); |
1950 | W.printNumber("NumArgs" , static_cast<uint32_t>(BI.getArgs().size())); |
1951 | ListScope Arguments(W, "Arguments" ); |
1952 | for (TypeIndex Arg : BI.getArgs()) |
1953 | printTypeIndex("ArgType" , Arg, StreamIPI); |
1954 | printTypeEnd(Record); |
1955 | }); |
1956 | |
1957 | // The given 'Element' refers to the current compilation unit. |
1958 | // All the args are references into the TPI/IPI stream. |
1959 | TypeIndex TIName = BI.getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile]; |
1960 | std::string Name = std::string(ids().getTypeName(Index: TIName)); |
1961 | |
1962 | // There are cases where LF_BUILDINFO fields are empty. |
1963 | if (!Name.empty()) |
1964 | Element->setName(Name); |
1965 | |
1966 | return Error::success(); |
1967 | } |
1968 | |
1969 | // LF_CLASS, LF_STRUCTURE, LF_INTERFACE (TPI) |
1970 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ClassRecord &Class, |
1971 | TypeIndex TI, LVElement *Element) { |
1972 | LLVM_DEBUG({ |
1973 | printTypeBegin(Record, TI, Element, StreamTPI); |
1974 | W.printNumber("MemberCount" , Class.getMemberCount()); |
1975 | printTypeIndex("FieldList" , Class.getFieldList(), StreamTPI); |
1976 | printTypeIndex("DerivedFrom" , Class.getDerivationList(), StreamTPI); |
1977 | printTypeIndex("VShape" , Class.getVTableShape(), StreamTPI); |
1978 | W.printNumber("SizeOf" , Class.getSize()); |
1979 | W.printString("Name" , Class.getName()); |
1980 | if (Class.hasUniqueName()) |
1981 | W.printString("UniqueName" , Class.getUniqueName()); |
1982 | printTypeEnd(Record); |
1983 | }); |
1984 | |
1985 | if (Element->getIsFinalized()) |
1986 | return Error::success(); |
1987 | Element->setIsFinalized(); |
1988 | |
1989 | LVScopeAggregate *Scope = static_cast<LVScopeAggregate *>(Element); |
1990 | if (!Scope) |
1991 | return Error::success(); |
1992 | |
1993 | Scope->setName(Class.getName()); |
1994 | if (Class.hasUniqueName()) |
1995 | Scope->setLinkageName(Class.getUniqueName()); |
1996 | Scope->setBitSize(Class.getSize() * DWARF_CHAR_BIT); |
1997 | |
1998 | if (Class.isNested()) { |
1999 | Scope->setIsNested(); |
2000 | createParents(ScopedName: Class.getName(), Element: Scope); |
2001 | } |
2002 | |
2003 | if (Class.isScoped()) |
2004 | Scope->setIsScoped(); |
2005 | |
2006 | // Nested types will be added to their parents at creation. The forward |
2007 | // references are only processed to finish the referenced element creation. |
2008 | if (!(Class.isNested() || Class.isScoped())) { |
2009 | if (LVScope *Namespace = Shared->NamespaceDeduction.get(ScopedName: Class.getName())) |
2010 | Namespace->addElement(Scope); |
2011 | else |
2012 | Reader->getCompileUnit()->addElement(Scope); |
2013 | } |
2014 | |
2015 | LazyRandomTypeCollection &Types = types(); |
2016 | TypeIndex TIFieldList = Class.getFieldList(); |
2017 | if (TIFieldList.isNoneType()) { |
2018 | TypeIndex ForwardType = Shared->ForwardReferences.find(Name: Class.getName()); |
2019 | if (!ForwardType.isNoneType()) { |
2020 | CVType CVReference = Types.getType(Index: ForwardType); |
2021 | TypeRecordKind RK = static_cast<TypeRecordKind>(CVReference.kind()); |
2022 | ClassRecord ReferenceRecord(RK); |
2023 | if (Error Err = TypeDeserializer::deserializeAs( |
2024 | CVT&: const_cast<CVType &>(CVReference), Record&: ReferenceRecord)) |
2025 | return Err; |
2026 | TIFieldList = ReferenceRecord.getFieldList(); |
2027 | } |
2028 | } |
2029 | |
2030 | if (!TIFieldList.isNoneType()) { |
2031 | // Pass down the TypeIndex 'TI' for the aggregate containing the field list. |
2032 | CVType CVFieldList = Types.getType(Index: TIFieldList); |
2033 | if (Error Err = finishVisitation(Record&: CVFieldList, TI, Element: Scope)) |
2034 | return Err; |
2035 | } |
2036 | |
2037 | return Error::success(); |
2038 | } |
2039 | |
2040 | // LF_ENUM (TPI) |
2041 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, EnumRecord &Enum, |
2042 | TypeIndex TI, LVElement *Element) { |
2043 | LLVM_DEBUG({ |
2044 | printTypeBegin(Record, TI, Element, StreamTPI); |
2045 | W.printNumber("NumEnumerators" , Enum.getMemberCount()); |
2046 | printTypeIndex("UnderlyingType" , Enum.getUnderlyingType(), StreamTPI); |
2047 | printTypeIndex("FieldListType" , Enum.getFieldList(), StreamTPI); |
2048 | W.printString("Name" , Enum.getName()); |
2049 | printTypeEnd(Record); |
2050 | }); |
2051 | |
2052 | LVScopeEnumeration *Scope = static_cast<LVScopeEnumeration *>(Element); |
2053 | if (!Scope) |
2054 | return Error::success(); |
2055 | |
2056 | if (Scope->getIsFinalized()) |
2057 | return Error::success(); |
2058 | Scope->setIsFinalized(); |
2059 | |
2060 | // Set the name, as in the case of nested, it would determine the relation |
2061 | // to any potential parent, via the LF_NESTTYPE record. |
2062 | Scope->setName(Enum.getName()); |
2063 | if (Enum.hasUniqueName()) |
2064 | Scope->setLinkageName(Enum.getUniqueName()); |
2065 | |
2066 | Scope->setType(getElement(StreamIdx: StreamTPI, TI: Enum.getUnderlyingType())); |
2067 | |
2068 | if (Enum.isNested()) { |
2069 | Scope->setIsNested(); |
2070 | createParents(ScopedName: Enum.getName(), Element: Scope); |
2071 | } |
2072 | |
2073 | if (Enum.isScoped()) { |
2074 | Scope->setIsScoped(); |
2075 | Scope->setIsEnumClass(); |
2076 | } |
2077 | |
2078 | // Nested types will be added to their parents at creation. |
2079 | if (!(Enum.isNested() || Enum.isScoped())) { |
2080 | if (LVScope *Namespace = Shared->NamespaceDeduction.get(ScopedName: Enum.getName())) |
2081 | Namespace->addElement(Scope); |
2082 | else |
2083 | Reader->getCompileUnit()->addElement(Scope); |
2084 | } |
2085 | |
2086 | TypeIndex TIFieldList = Enum.getFieldList(); |
2087 | if (!TIFieldList.isNoneType()) { |
2088 | LazyRandomTypeCollection &Types = types(); |
2089 | CVType CVFieldList = Types.getType(Index: TIFieldList); |
2090 | if (Error Err = finishVisitation(Record&: CVFieldList, TI: TIFieldList, Element: Scope)) |
2091 | return Err; |
2092 | } |
2093 | |
2094 | return Error::success(); |
2095 | } |
2096 | |
2097 | // LF_FIELDLIST (TPI) |
2098 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, |
2099 | FieldListRecord &FieldList, |
2100 | TypeIndex TI, LVElement *Element) { |
2101 | LLVM_DEBUG({ |
2102 | printTypeBegin(Record, TI, Element, StreamTPI); |
2103 | printTypeEnd(Record); |
2104 | }); |
2105 | |
2106 | if (Error Err = visitFieldListMemberStream(TI, Element, FieldList: FieldList.Data)) |
2107 | return Err; |
2108 | |
2109 | return Error::success(); |
2110 | } |
2111 | |
2112 | // LF_FUNC_ID (TPI)/(IPI) |
2113 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, FuncIdRecord &Func, |
2114 | TypeIndex TI, LVElement *Element) { |
2115 | // ParentScope and FunctionType are references into the TPI stream. |
2116 | LLVM_DEBUG({ |
2117 | printTypeBegin(Record, TI, Element, StreamIPI); |
2118 | printTypeIndex("ParentScope" , Func.getParentScope(), StreamTPI); |
2119 | printTypeIndex("FunctionType" , Func.getFunctionType(), StreamTPI); |
2120 | W.printString("Name" , Func.getName()); |
2121 | printTypeEnd(Record); |
2122 | }); |
2123 | |
2124 | // The TypeIndex (LF_PROCEDURE) returned by 'getFunctionType' is the |
2125 | // function propotype, we need to use the function definition. |
2126 | if (LVScope *FunctionDcl = static_cast<LVScope *>(Element)) { |
2127 | // For inlined functions, the inlined instance has been already processed |
2128 | // (all its information is contained in the Symbols section). |
2129 | // 'Element' points to the created 'abstract' (out-of-line) function. |
2130 | // Use the parent scope information to allocate it to the correct scope. |
2131 | LazyRandomTypeCollection &Types = types(); |
2132 | TypeIndex TIParent = Func.getParentScope(); |
2133 | if (FunctionDcl->getIsInlinedAbstract()) { |
2134 | FunctionDcl->setName(Func.getName()); |
2135 | if (TIParent.isNoneType()) |
2136 | Reader->getCompileUnit()->addElement(Scope: FunctionDcl); |
2137 | } |
2138 | |
2139 | if (!TIParent.isNoneType()) { |
2140 | CVType CVParentScope = ids().getType(Index: TIParent); |
2141 | if (Error Err = finishVisitation(Record&: CVParentScope, TI: TIParent, Element: FunctionDcl)) |
2142 | return Err; |
2143 | } |
2144 | |
2145 | TypeIndex TIFunctionType = Func.getFunctionType(); |
2146 | CVType CVFunctionType = Types.getType(Index: TIFunctionType); |
2147 | if (Error Err = |
2148 | finishVisitation(Record&: CVFunctionType, TI: TIFunctionType, Element: FunctionDcl)) |
2149 | return Err; |
2150 | |
2151 | FunctionDcl->setIsFinalized(); |
2152 | } |
2153 | |
2154 | return Error::success(); |
2155 | } |
2156 | |
2157 | // LF_LABEL (TPI) |
2158 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, LabelRecord &LR, |
2159 | TypeIndex TI, LVElement *Element) { |
2160 | LLVM_DEBUG({ |
2161 | printTypeBegin(Record, TI, Element, StreamTPI); |
2162 | printTypeEnd(Record); |
2163 | }); |
2164 | return Error::success(); |
2165 | } |
2166 | |
2167 | // LF_MFUNC_ID (TPI)/(IPI) |
2168 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, MemberFuncIdRecord &Id, |
2169 | TypeIndex TI, LVElement *Element) { |
2170 | // ClassType and FunctionType are references into the TPI stream. |
2171 | LLVM_DEBUG({ |
2172 | printTypeBegin(Record, TI, Element, StreamIPI); |
2173 | printTypeIndex("ClassType" , Id.getClassType(), StreamTPI); |
2174 | printTypeIndex("FunctionType" , Id.getFunctionType(), StreamTPI); |
2175 | W.printString("Name" , Id.getName()); |
2176 | printTypeEnd(Record); |
2177 | }); |
2178 | |
2179 | LVScope *FunctionDcl = static_cast<LVScope *>(Element); |
2180 | if (FunctionDcl->getIsInlinedAbstract()) { |
2181 | // For inlined functions, the inlined instance has been already processed |
2182 | // (all its information is contained in the Symbols section). |
2183 | // 'Element' points to the created 'abstract' (out-of-line) function. |
2184 | // Use the parent scope information to allocate it to the correct scope. |
2185 | if (LVScope *Class = static_cast<LVScope *>( |
2186 | Shared->TypeRecords.find(StreamIdx: StreamTPI, TI: Id.getClassType()))) |
2187 | Class->addElement(Scope: FunctionDcl); |
2188 | } |
2189 | |
2190 | TypeIndex TIFunctionType = Id.getFunctionType(); |
2191 | CVType CVFunction = types().getType(Index: TIFunctionType); |
2192 | if (Error Err = finishVisitation(Record&: CVFunction, TI: TIFunctionType, Element)) |
2193 | return Err; |
2194 | |
2195 | return Error::success(); |
2196 | } |
2197 | |
2198 | // LF_MFUNCTION (TPI) |
2199 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, |
2200 | MemberFunctionRecord &MF, TypeIndex TI, |
2201 | LVElement *Element) { |
2202 | LLVM_DEBUG({ |
2203 | printTypeBegin(Record, TI, Element, StreamTPI); |
2204 | printTypeIndex("ReturnType" , MF.getReturnType(), StreamTPI); |
2205 | printTypeIndex("ClassType" , MF.getClassType(), StreamTPI); |
2206 | printTypeIndex("ThisType" , MF.getThisType(), StreamTPI); |
2207 | W.printNumber("NumParameters" , MF.getParameterCount()); |
2208 | printTypeIndex("ArgListType" , MF.getArgumentList(), StreamTPI); |
2209 | W.printNumber("ThisAdjustment" , MF.getThisPointerAdjustment()); |
2210 | printTypeEnd(Record); |
2211 | }); |
2212 | |
2213 | if (LVScope *MemberFunction = static_cast<LVScope *>(Element)) { |
2214 | LVElement *Class = getElement(StreamIdx: StreamTPI, TI: MF.getClassType()); |
2215 | |
2216 | MemberFunction->setIsFinalized(); |
2217 | MemberFunction->setType(getElement(StreamIdx: StreamTPI, TI: MF.getReturnType())); |
2218 | MemberFunction->setOffset(TI.getIndex()); |
2219 | MemberFunction->setOffsetFromTypeIndex(); |
2220 | |
2221 | if (ProcessArgumentList) { |
2222 | ProcessArgumentList = false; |
2223 | |
2224 | if (!MemberFunction->getIsStatic()) { |
2225 | LVElement *ThisPointer = getElement(StreamIdx: StreamTPI, TI: MF.getThisType()); |
2226 | // When creating the 'this' pointer, check if it points to a reference. |
2227 | ThisPointer->setType(Class); |
2228 | LVSymbol *This = |
2229 | createParameter(Element: ThisPointer, Name: StringRef(), Parent: MemberFunction); |
2230 | This->setIsArtificial(); |
2231 | } |
2232 | |
2233 | // Create formal parameters. |
2234 | LazyRandomTypeCollection &Types = types(); |
2235 | CVType CVArguments = Types.getType(Index: MF.getArgumentList()); |
2236 | if (Error Err = finishVisitation(Record&: CVArguments, TI: MF.getArgumentList(), |
2237 | Element: MemberFunction)) |
2238 | return Err; |
2239 | } |
2240 | } |
2241 | |
2242 | return Error::success(); |
2243 | } |
2244 | |
2245 | // LF_METHODLIST (TPI) |
2246 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, |
2247 | MethodOverloadListRecord &Overloads, |
2248 | TypeIndex TI, LVElement *Element) { |
2249 | LLVM_DEBUG({ |
2250 | printTypeBegin(Record, TI, Element, StreamTPI); |
2251 | printTypeEnd(Record); |
2252 | }); |
2253 | |
2254 | for (OneMethodRecord &Method : Overloads.Methods) { |
2255 | CVMemberRecord Record; |
2256 | Record.Kind = LF_METHOD; |
2257 | Method.Name = OverloadedMethodName; |
2258 | if (Error Err = visitKnownMember(Record, Method, TI, Element)) |
2259 | return Err; |
2260 | } |
2261 | |
2262 | return Error::success(); |
2263 | } |
2264 | |
2265 | // LF_MODIFIER (TPI) |
2266 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ModifierRecord &Mod, |
2267 | TypeIndex TI, LVElement *Element) { |
2268 | LLVM_DEBUG({ |
2269 | printTypeBegin(Record, TI, Element, StreamTPI); |
2270 | printTypeIndex("ModifiedType" , Mod.getModifiedType(), StreamTPI); |
2271 | printTypeEnd(Record); |
2272 | }); |
2273 | |
2274 | // Create the modified type, which will be attached to the type(s) that |
2275 | // contains the modifiers. |
2276 | LVElement *ModifiedType = getElement(StreamIdx: StreamTPI, TI: Mod.getModifiedType()); |
2277 | |
2278 | // At this point the types recording the qualifiers do not have a |
2279 | // scope parent. They must be assigned to the current compile unit. |
2280 | LVScopeCompileUnit *CompileUnit = Reader->getCompileUnit(); |
2281 | |
2282 | // The incoming element does not have a defined kind. Use the given |
2283 | // modifiers to complete its type. A type can have more than one modifier; |
2284 | // in that case, we have to create an extra type to have the other modifier. |
2285 | LVType *LastLink = static_cast<LVType *>(Element); |
2286 | if (!LastLink->getParentScope()) |
2287 | CompileUnit->addElement(Type: LastLink); |
2288 | |
2289 | bool SeenModifier = false; |
2290 | uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); |
2291 | if (Mods & uint16_t(ModifierOptions::Const)) { |
2292 | SeenModifier = true; |
2293 | LastLink->setTag(dwarf::DW_TAG_const_type); |
2294 | LastLink->setIsConst(); |
2295 | LastLink->setName("const" ); |
2296 | } |
2297 | if (Mods & uint16_t(ModifierOptions::Volatile)) { |
2298 | if (SeenModifier) { |
2299 | LVType *Volatile = Reader->createType(); |
2300 | Volatile->setIsModifier(); |
2301 | LastLink->setType(Volatile); |
2302 | LastLink = Volatile; |
2303 | CompileUnit->addElement(Type: LastLink); |
2304 | } |
2305 | LastLink->setTag(dwarf::DW_TAG_volatile_type); |
2306 | LastLink->setIsVolatile(); |
2307 | LastLink->setName("volatile" ); |
2308 | } |
2309 | if (Mods & uint16_t(ModifierOptions::Unaligned)) { |
2310 | if (SeenModifier) { |
2311 | LVType *Unaligned = Reader->createType(); |
2312 | Unaligned->setIsModifier(); |
2313 | LastLink->setType(Unaligned); |
2314 | LastLink = Unaligned; |
2315 | CompileUnit->addElement(Type: LastLink); |
2316 | } |
2317 | LastLink->setTag(dwarf::DW_TAG_unaligned); |
2318 | LastLink->setIsUnaligned(); |
2319 | LastLink->setName("unaligned" ); |
2320 | } |
2321 | |
2322 | LastLink->setType(ModifiedType); |
2323 | return Error::success(); |
2324 | } |
2325 | |
2326 | // LF_POINTER (TPI) |
2327 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, PointerRecord &Ptr, |
2328 | TypeIndex TI, LVElement *Element) { |
2329 | LLVM_DEBUG({ |
2330 | printTypeBegin(Record, TI, Element, StreamTPI); |
2331 | printTypeIndex("PointeeType" , Ptr.getReferentType(), StreamTPI); |
2332 | W.printNumber("IsFlat" , Ptr.isFlat()); |
2333 | W.printNumber("IsConst" , Ptr.isConst()); |
2334 | W.printNumber("IsVolatile" , Ptr.isVolatile()); |
2335 | W.printNumber("IsUnaligned" , Ptr.isUnaligned()); |
2336 | W.printNumber("IsRestrict" , Ptr.isRestrict()); |
2337 | W.printNumber("IsThisPtr&" , Ptr.isLValueReferenceThisPtr()); |
2338 | W.printNumber("IsThisPtr&&" , Ptr.isRValueReferenceThisPtr()); |
2339 | W.printNumber("SizeOf" , Ptr.getSize()); |
2340 | |
2341 | if (Ptr.isPointerToMember()) { |
2342 | const MemberPointerInfo &MI = Ptr.getMemberInfo(); |
2343 | printTypeIndex("ClassType" , MI.getContainingType(), StreamTPI); |
2344 | } |
2345 | printTypeEnd(Record); |
2346 | }); |
2347 | |
2348 | // Find the pointed-to type. |
2349 | LVType *Pointer = static_cast<LVType *>(Element); |
2350 | LVElement *Pointee = nullptr; |
2351 | |
2352 | PointerMode Mode = Ptr.getMode(); |
2353 | Pointee = Ptr.isPointerToMember() |
2354 | ? Shared->TypeRecords.find(StreamIdx: StreamTPI, TI: Ptr.getReferentType()) |
2355 | : getElement(StreamIdx: StreamTPI, TI: Ptr.getReferentType()); |
2356 | |
2357 | // At this point the types recording the qualifiers do not have a |
2358 | // scope parent. They must be assigned to the current compile unit. |
2359 | LVScopeCompileUnit *CompileUnit = Reader->getCompileUnit(); |
2360 | |
2361 | // Order for the different modifiers: |
2362 | // <restrict> <pointer, Reference, ValueReference> <const, volatile> |
2363 | // Const and volatile already processed. |
2364 | bool SeenModifier = false; |
2365 | LVType *LastLink = Pointer; |
2366 | if (!LastLink->getParentScope()) |
2367 | CompileUnit->addElement(Type: LastLink); |
2368 | |
2369 | if (Ptr.isRestrict()) { |
2370 | SeenModifier = true; |
2371 | LVType *Restrict = Reader->createType(); |
2372 | Restrict->setTag(dwarf::DW_TAG_restrict_type); |
2373 | Restrict->setIsRestrict(); |
2374 | Restrict->setName("restrict" ); |
2375 | LastLink->setType(Restrict); |
2376 | LastLink = Restrict; |
2377 | CompileUnit->addElement(Type: LastLink); |
2378 | } |
2379 | if (Mode == PointerMode::LValueReference) { |
2380 | if (SeenModifier) { |
2381 | LVType *LReference = Reader->createType(); |
2382 | LReference->setIsModifier(); |
2383 | LastLink->setType(LReference); |
2384 | LastLink = LReference; |
2385 | CompileUnit->addElement(Type: LastLink); |
2386 | } |
2387 | LastLink->setTag(dwarf::DW_TAG_reference_type); |
2388 | LastLink->setIsReference(); |
2389 | LastLink->setName("&" ); |
2390 | } |
2391 | if (Mode == PointerMode::RValueReference) { |
2392 | if (SeenModifier) { |
2393 | LVType *RReference = Reader->createType(); |
2394 | RReference->setIsModifier(); |
2395 | LastLink->setType(RReference); |
2396 | LastLink = RReference; |
2397 | CompileUnit->addElement(Type: LastLink); |
2398 | } |
2399 | LastLink->setTag(dwarf::DW_TAG_rvalue_reference_type); |
2400 | LastLink->setIsRvalueReference(); |
2401 | LastLink->setName("&&" ); |
2402 | } |
2403 | |
2404 | // When creating the pointer, check if it points to a reference. |
2405 | LastLink->setType(Pointee); |
2406 | return Error::success(); |
2407 | } |
2408 | |
2409 | // LF_PROCEDURE (TPI) |
2410 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ProcedureRecord &Proc, |
2411 | TypeIndex TI, LVElement *Element) { |
2412 | LLVM_DEBUG({ |
2413 | printTypeBegin(Record, TI, Element, StreamTPI); |
2414 | printTypeIndex("ReturnType" , Proc.getReturnType(), StreamTPI); |
2415 | W.printNumber("NumParameters" , Proc.getParameterCount()); |
2416 | printTypeIndex("ArgListType" , Proc.getArgumentList(), StreamTPI); |
2417 | printTypeEnd(Record); |
2418 | }); |
2419 | |
2420 | // There is no need to traverse the argument list, as the CodeView format |
2421 | // declares the parameters as a 'S_LOCAL' symbol tagged as parameter. |
2422 | // Only process parameters when dealing with inline functions. |
2423 | if (LVScope *FunctionDcl = static_cast<LVScope *>(Element)) { |
2424 | FunctionDcl->setType(getElement(StreamIdx: StreamTPI, TI: Proc.getReturnType())); |
2425 | |
2426 | if (ProcessArgumentList) { |
2427 | ProcessArgumentList = false; |
2428 | // Create formal parameters. |
2429 | LazyRandomTypeCollection &Types = types(); |
2430 | CVType CVArguments = Types.getType(Index: Proc.getArgumentList()); |
2431 | if (Error Err = finishVisitation(Record&: CVArguments, TI: Proc.getArgumentList(), |
2432 | Element: FunctionDcl)) |
2433 | return Err; |
2434 | } |
2435 | } |
2436 | |
2437 | return Error::success(); |
2438 | } |
2439 | |
2440 | // LF_UNION (TPI) |
2441 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, UnionRecord &Union, |
2442 | TypeIndex TI, LVElement *Element) { |
2443 | LLVM_DEBUG({ |
2444 | printTypeBegin(Record, TI, Element, StreamTPI); |
2445 | W.printNumber("MemberCount" , Union.getMemberCount()); |
2446 | printTypeIndex("FieldList" , Union.getFieldList(), StreamTPI); |
2447 | W.printNumber("SizeOf" , Union.getSize()); |
2448 | W.printString("Name" , Union.getName()); |
2449 | if (Union.hasUniqueName()) |
2450 | W.printString("UniqueName" , Union.getUniqueName()); |
2451 | printTypeEnd(Record); |
2452 | }); |
2453 | |
2454 | LVScopeAggregate *Scope = static_cast<LVScopeAggregate *>(Element); |
2455 | if (!Scope) |
2456 | return Error::success(); |
2457 | |
2458 | if (Scope->getIsFinalized()) |
2459 | return Error::success(); |
2460 | Scope->setIsFinalized(); |
2461 | |
2462 | Scope->setName(Union.getName()); |
2463 | if (Union.hasUniqueName()) |
2464 | Scope->setLinkageName(Union.getUniqueName()); |
2465 | Scope->setBitSize(Union.getSize() * DWARF_CHAR_BIT); |
2466 | |
2467 | if (Union.isNested()) { |
2468 | Scope->setIsNested(); |
2469 | createParents(ScopedName: Union.getName(), Element: Scope); |
2470 | } else { |
2471 | if (LVScope *Namespace = Shared->NamespaceDeduction.get(ScopedName: Union.getName())) |
2472 | Namespace->addElement(Scope); |
2473 | else |
2474 | Reader->getCompileUnit()->addElement(Scope); |
2475 | } |
2476 | |
2477 | if (!Union.getFieldList().isNoneType()) { |
2478 | LazyRandomTypeCollection &Types = types(); |
2479 | // Pass down the TypeIndex 'TI' for the aggregate containing the field list. |
2480 | CVType CVFieldList = Types.getType(Index: Union.getFieldList()); |
2481 | if (Error Err = finishVisitation(Record&: CVFieldList, TI, Element: Scope)) |
2482 | return Err; |
2483 | } |
2484 | |
2485 | return Error::success(); |
2486 | } |
2487 | |
2488 | // LF_TYPESERVER2 (TPI) |
2489 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, TypeServer2Record &TS, |
2490 | TypeIndex TI, LVElement *Element) { |
2491 | LLVM_DEBUG({ |
2492 | printTypeBegin(Record, TI, Element, StreamTPI); |
2493 | W.printString("Guid" , formatv("{0}" , TS.getGuid()).str()); |
2494 | W.printNumber("Age" , TS.getAge()); |
2495 | W.printString("Name" , TS.getName()); |
2496 | printTypeEnd(Record); |
2497 | }); |
2498 | return Error::success(); |
2499 | } |
2500 | |
2501 | // LF_VFTABLE (TPI) |
2502 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, VFTableRecord &VFT, |
2503 | TypeIndex TI, LVElement *Element) { |
2504 | LLVM_DEBUG({ |
2505 | printTypeBegin(Record, TI, Element, StreamTPI); |
2506 | printTypeIndex("CompleteClass" , VFT.getCompleteClass(), StreamTPI); |
2507 | printTypeIndex("OverriddenVFTable" , VFT.getOverriddenVTable(), StreamTPI); |
2508 | W.printHex("VFPtrOffset" , VFT.getVFPtrOffset()); |
2509 | W.printString("VFTableName" , VFT.getName()); |
2510 | for (const StringRef &N : VFT.getMethodNames()) |
2511 | W.printString("MethodName" , N); |
2512 | printTypeEnd(Record); |
2513 | }); |
2514 | return Error::success(); |
2515 | } |
2516 | |
2517 | // LF_VTSHAPE (TPI) |
2518 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, |
2519 | VFTableShapeRecord &Shape, |
2520 | TypeIndex TI, LVElement *Element) { |
2521 | LLVM_DEBUG({ |
2522 | printTypeBegin(Record, TI, Element, StreamTPI); |
2523 | W.printNumber("VFEntryCount" , Shape.getEntryCount()); |
2524 | printTypeEnd(Record); |
2525 | }); |
2526 | return Error::success(); |
2527 | } |
2528 | |
2529 | // LF_SUBSTR_LIST (TPI)/(IPI) |
2530 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, |
2531 | StringListRecord &Strings, |
2532 | TypeIndex TI, LVElement *Element) { |
2533 | // All the indices are references into the TPI/IPI stream. |
2534 | LLVM_DEBUG({ |
2535 | printTypeBegin(Record, TI, Element, StreamIPI); |
2536 | ArrayRef<TypeIndex> Indices = Strings.getIndices(); |
2537 | uint32_t Size = Indices.size(); |
2538 | W.printNumber("NumStrings" , Size); |
2539 | ListScope Arguments(W, "Strings" ); |
2540 | for (uint32_t I = 0; I < Size; ++I) |
2541 | printTypeIndex("String" , Indices[I], StreamIPI); |
2542 | printTypeEnd(Record); |
2543 | }); |
2544 | return Error::success(); |
2545 | } |
2546 | |
2547 | // LF_STRING_ID (TPI)/(IPI) |
2548 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, StringIdRecord &String, |
2549 | TypeIndex TI, LVElement *Element) { |
2550 | // All args are references into the TPI/IPI stream. |
2551 | LLVM_DEBUG({ |
2552 | printTypeIndex("\nTI" , TI, StreamIPI); |
2553 | printTypeIndex("Id" , String.getId(), StreamIPI); |
2554 | W.printString("StringData" , String.getString()); |
2555 | }); |
2556 | |
2557 | if (LVScope *Namespace = Shared->NamespaceDeduction.get( |
2558 | ScopedName: String.getString(), /*CheckScope=*/false)) { |
2559 | // The function is already at different scope. In order to reflect |
2560 | // the correct parent, move it to the namespace. |
2561 | if (LVScope *Scope = Element->getParentScope()) |
2562 | Scope->removeElement(Element); |
2563 | Namespace->addElement(Element); |
2564 | } |
2565 | |
2566 | return Error::success(); |
2567 | } |
2568 | |
2569 | // LF_UDT_SRC_LINE (TPI)/(IPI) |
2570 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, |
2571 | UdtSourceLineRecord &SourceLine, |
2572 | TypeIndex TI, LVElement *Element) { |
2573 | // All args are references into the TPI/IPI stream. |
2574 | LLVM_DEBUG({ |
2575 | printTypeIndex("\nTI" , TI, StreamIPI); |
2576 | printTypeIndex("UDT" , SourceLine.getUDT(), StreamIPI); |
2577 | printTypeIndex("SourceFile" , SourceLine.getSourceFile(), StreamIPI); |
2578 | W.printNumber("LineNumber" , SourceLine.getLineNumber()); |
2579 | }); |
2580 | return Error::success(); |
2581 | } |
2582 | |
2583 | // LF_UDT_MOD_SRC_LINE (TPI)/(IPI) |
2584 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, |
2585 | UdtModSourceLineRecord &ModSourceLine, |
2586 | TypeIndex TI, LVElement *Element) { |
2587 | // All args are references into the TPI/IPI stream. |
2588 | LLVM_DEBUG({ |
2589 | printTypeBegin(Record, TI, Element, StreamIPI); |
2590 | printTypeIndex("\nTI" , TI, StreamIPI); |
2591 | printTypeIndex("UDT" , ModSourceLine.getUDT(), StreamIPI); |
2592 | printTypeIndex("SourceFile" , ModSourceLine.getSourceFile(), StreamIPI); |
2593 | W.printNumber("LineNumber" , ModSourceLine.getLineNumber()); |
2594 | W.printNumber("Module" , ModSourceLine.getModule()); |
2595 | printTypeEnd(Record); |
2596 | }); |
2597 | return Error::success(); |
2598 | } |
2599 | |
2600 | // LF_PRECOMP (TPI) |
2601 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, PrecompRecord &Precomp, |
2602 | TypeIndex TI, LVElement *Element) { |
2603 | LLVM_DEBUG({ |
2604 | printTypeBegin(Record, TI, Element, StreamTPI); |
2605 | W.printHex("StartIndex" , Precomp.getStartTypeIndex()); |
2606 | W.printHex("Count" , Precomp.getTypesCount()); |
2607 | W.printHex("Signature" , Precomp.getSignature()); |
2608 | W.printString("PrecompFile" , Precomp.getPrecompFilePath()); |
2609 | printTypeEnd(Record); |
2610 | }); |
2611 | return Error::success(); |
2612 | } |
2613 | |
2614 | // LF_ENDPRECOMP (TPI) |
2615 | Error LVLogicalVisitor::visitKnownRecord(CVType &Record, |
2616 | EndPrecompRecord &EndPrecomp, |
2617 | TypeIndex TI, LVElement *Element) { |
2618 | LLVM_DEBUG({ |
2619 | printTypeBegin(Record, TI, Element, StreamTPI); |
2620 | W.printHex("Signature" , EndPrecomp.getSignature()); |
2621 | printTypeEnd(Record); |
2622 | }); |
2623 | return Error::success(); |
2624 | } |
2625 | |
2626 | Error LVLogicalVisitor::visitUnknownMember(CVMemberRecord &Record, |
2627 | TypeIndex TI) { |
2628 | LLVM_DEBUG({ W.printHex("UnknownMember" , unsigned(Record.Kind)); }); |
2629 | return Error::success(); |
2630 | } |
2631 | |
2632 | // LF_BCLASS, LF_BINTERFACE |
2633 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2634 | BaseClassRecord &Base, TypeIndex TI, |
2635 | LVElement *Element) { |
2636 | LLVM_DEBUG({ |
2637 | printMemberBegin(Record, TI, Element, StreamTPI); |
2638 | printTypeIndex("BaseType" , Base.getBaseType(), StreamTPI); |
2639 | W.printHex("BaseOffset" , Base.getBaseOffset()); |
2640 | printMemberEnd(Record); |
2641 | }); |
2642 | |
2643 | createElement(Kind: Record.Kind); |
2644 | if (LVSymbol *Symbol = CurrentSymbol) { |
2645 | LVElement *BaseClass = getElement(StreamIdx: StreamTPI, TI: Base.getBaseType()); |
2646 | Symbol->setName(BaseClass->getName()); |
2647 | Symbol->setType(BaseClass); |
2648 | Symbol->setAccessibilityCode(Base.getAccess()); |
2649 | static_cast<LVScope *>(Element)->addElement(Symbol); |
2650 | } |
2651 | |
2652 | return Error::success(); |
2653 | } |
2654 | |
2655 | // LF_MEMBER |
2656 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2657 | DataMemberRecord &Field, TypeIndex TI, |
2658 | LVElement *Element) { |
2659 | LLVM_DEBUG({ |
2660 | printMemberBegin(Record, TI, Element, StreamTPI); |
2661 | printTypeIndex("Type" , Field.getType(), StreamTPI); |
2662 | W.printHex("FieldOffset" , Field.getFieldOffset()); |
2663 | W.printString("Name" , Field.getName()); |
2664 | printMemberEnd(Record); |
2665 | }); |
2666 | |
2667 | // Create the data member. |
2668 | createDataMember(Record, Parent: static_cast<LVScope *>(Element), Name: Field.getName(), |
2669 | Type: Field.getType(), Access: Field.getAccess()); |
2670 | return Error::success(); |
2671 | } |
2672 | |
2673 | // LF_ENUMERATE |
2674 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2675 | EnumeratorRecord &Enum, TypeIndex TI, |
2676 | LVElement *Element) { |
2677 | LLVM_DEBUG({ |
2678 | printMemberBegin(Record, TI, Element, StreamTPI); |
2679 | W.printNumber("EnumValue" , Enum.getValue()); |
2680 | W.printString("Name" , Enum.getName()); |
2681 | printMemberEnd(Record); |
2682 | }); |
2683 | |
2684 | createElement(Kind: Record.Kind); |
2685 | if (LVType *Type = CurrentType) { |
2686 | Type->setName(Enum.getName()); |
2687 | SmallString<16> Value; |
2688 | Enum.getValue().toString(Str&: Value, Radix: 16, Signed: true, formatAsCLiteral: true); |
2689 | Type->setValue(Value); |
2690 | static_cast<LVScope *>(Element)->addElement(Type: CurrentType); |
2691 | } |
2692 | |
2693 | return Error::success(); |
2694 | } |
2695 | |
2696 | // LF_INDEX |
2697 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2698 | ListContinuationRecord &Cont, |
2699 | TypeIndex TI, LVElement *Element) { |
2700 | LLVM_DEBUG({ |
2701 | printMemberBegin(Record, TI, Element, StreamTPI); |
2702 | printTypeIndex("ContinuationIndex" , Cont.getContinuationIndex(), StreamTPI); |
2703 | printMemberEnd(Record); |
2704 | }); |
2705 | return Error::success(); |
2706 | } |
2707 | |
2708 | // LF_NESTTYPE |
2709 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2710 | NestedTypeRecord &Nested, TypeIndex TI, |
2711 | LVElement *Element) { |
2712 | LLVM_DEBUG({ |
2713 | printMemberBegin(Record, TI, Element, StreamTPI); |
2714 | printTypeIndex("Type" , Nested.getNestedType(), StreamTPI); |
2715 | W.printString("Name" , Nested.getName()); |
2716 | printMemberEnd(Record); |
2717 | }); |
2718 | |
2719 | if (LVElement *Typedef = createElement(Kind: SymbolKind::S_UDT)) { |
2720 | Typedef->setName(Nested.getName()); |
2721 | LVElement *NestedType = getElement(StreamIdx: StreamTPI, TI: Nested.getNestedType()); |
2722 | Typedef->setType(NestedType); |
2723 | LVScope *Scope = static_cast<LVScope *>(Element); |
2724 | Scope->addElement(Element: Typedef); |
2725 | |
2726 | if (NestedType && NestedType->getIsNested()) { |
2727 | // 'Element' is an aggregate type that may contains this nested type |
2728 | // definition. Used their scoped names, to decide on their relationship. |
2729 | StringRef RecordName = getRecordName(Types&: types(), TI); |
2730 | |
2731 | StringRef NestedTypeName = NestedType->getName(); |
2732 | if (NestedTypeName.size() && RecordName.size()) { |
2733 | StringRef OuterComponent; |
2734 | std::tie(args&: OuterComponent, args: std::ignore) = |
2735 | getInnerComponent(Name: NestedTypeName); |
2736 | // We have an already created nested type. Add it to the current scope |
2737 | // and update all its children if any. |
2738 | if (OuterComponent.size() && OuterComponent == RecordName) { |
2739 | if (!NestedType->getIsScopedAlready()) { |
2740 | Scope->addElement(Element: NestedType); |
2741 | NestedType->setIsScopedAlready(); |
2742 | NestedType->updateLevel(Parent: Scope); |
2743 | } |
2744 | Typedef->resetIncludeInPrint(); |
2745 | } |
2746 | } |
2747 | } |
2748 | } |
2749 | |
2750 | return Error::success(); |
2751 | } |
2752 | |
2753 | // LF_ONEMETHOD |
2754 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2755 | OneMethodRecord &Method, TypeIndex TI, |
2756 | LVElement *Element) { |
2757 | LLVM_DEBUG({ |
2758 | printMemberBegin(Record, TI, Element, StreamTPI); |
2759 | printTypeIndex("Type" , Method.getType(), StreamTPI); |
2760 | // If virtual, then read the vftable offset. |
2761 | if (Method.isIntroducingVirtual()) |
2762 | W.printHex("VFTableOffset" , Method.getVFTableOffset()); |
2763 | W.printString("Name" , Method.getName()); |
2764 | printMemberEnd(Record); |
2765 | }); |
2766 | |
2767 | // All the LF_ONEMETHOD objects share the same type description. |
2768 | // We have to create a scope object for each one and get the required |
2769 | // information from the LF_MFUNCTION object. |
2770 | ProcessArgumentList = true; |
2771 | if (LVElement *MemberFunction = createElement(Kind: TypeLeafKind::LF_ONEMETHOD)) { |
2772 | MemberFunction->setIsFinalized(); |
2773 | static_cast<LVScope *>(Element)->addElement(Element: MemberFunction); |
2774 | |
2775 | MemberFunction->setName(Method.getName()); |
2776 | MemberFunction->setAccessibilityCode(Method.getAccess()); |
2777 | |
2778 | MethodKind Kind = Method.getMethodKind(); |
2779 | if (Kind == MethodKind::Static) |
2780 | MemberFunction->setIsStatic(); |
2781 | MemberFunction->setVirtualityCode(Kind); |
2782 | |
2783 | MethodOptions Flags = Method.Attrs.getFlags(); |
2784 | if (MethodOptions::CompilerGenerated == |
2785 | (Flags & MethodOptions::CompilerGenerated)) |
2786 | MemberFunction->setIsArtificial(); |
2787 | |
2788 | LazyRandomTypeCollection &Types = types(); |
2789 | CVType CVMethodType = Types.getType(Index: Method.getType()); |
2790 | if (Error Err = |
2791 | finishVisitation(Record&: CVMethodType, TI: Method.getType(), Element: MemberFunction)) |
2792 | return Err; |
2793 | } |
2794 | ProcessArgumentList = false; |
2795 | |
2796 | return Error::success(); |
2797 | } |
2798 | |
2799 | // LF_METHOD |
2800 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2801 | OverloadedMethodRecord &Method, |
2802 | TypeIndex TI, LVElement *Element) { |
2803 | LLVM_DEBUG({ |
2804 | printMemberBegin(Record, TI, Element, StreamTPI); |
2805 | W.printHex("MethodCount" , Method.getNumOverloads()); |
2806 | printTypeIndex("MethodListIndex" , Method.getMethodList(), StreamTPI); |
2807 | W.printString("Name" , Method.getName()); |
2808 | printMemberEnd(Record); |
2809 | }); |
2810 | |
2811 | // Record the overloaded method name, which will be used during the |
2812 | // traversal of the method list. |
2813 | LazyRandomTypeCollection &Types = types(); |
2814 | OverloadedMethodName = Method.getName(); |
2815 | CVType CVMethods = Types.getType(Index: Method.getMethodList()); |
2816 | if (Error Err = finishVisitation(Record&: CVMethods, TI: Method.getMethodList(), Element)) |
2817 | return Err; |
2818 | |
2819 | return Error::success(); |
2820 | } |
2821 | |
2822 | // LF_STMEMBER |
2823 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2824 | StaticDataMemberRecord &Field, |
2825 | TypeIndex TI, LVElement *Element) { |
2826 | LLVM_DEBUG({ |
2827 | printMemberBegin(Record, TI, Element, StreamTPI); |
2828 | printTypeIndex("Type" , Field.getType(), StreamTPI); |
2829 | W.printString("Name" , Field.getName()); |
2830 | printMemberEnd(Record); |
2831 | }); |
2832 | |
2833 | // Create the data member. |
2834 | createDataMember(Record, Parent: static_cast<LVScope *>(Element), Name: Field.getName(), |
2835 | Type: Field.getType(), Access: Field.getAccess()); |
2836 | return Error::success(); |
2837 | } |
2838 | |
2839 | // LF_VFUNCTAB |
2840 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2841 | VFPtrRecord &VFTable, TypeIndex TI, |
2842 | LVElement *Element) { |
2843 | LLVM_DEBUG({ |
2844 | printMemberBegin(Record, TI, Element, StreamTPI); |
2845 | printTypeIndex("Type" , VFTable.getType(), StreamTPI); |
2846 | printMemberEnd(Record); |
2847 | }); |
2848 | return Error::success(); |
2849 | } |
2850 | |
2851 | // LF_VBCLASS, LF_IVBCLASS |
2852 | Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, |
2853 | VirtualBaseClassRecord &Base, |
2854 | TypeIndex TI, LVElement *Element) { |
2855 | LLVM_DEBUG({ |
2856 | printMemberBegin(Record, TI, Element, StreamTPI); |
2857 | printTypeIndex("BaseType" , Base.getBaseType(), StreamTPI); |
2858 | printTypeIndex("VBPtrType" , Base.getVBPtrType(), StreamTPI); |
2859 | W.printHex("VBPtrOffset" , Base.getVBPtrOffset()); |
2860 | W.printHex("VBTableIndex" , Base.getVTableIndex()); |
2861 | printMemberEnd(Record); |
2862 | }); |
2863 | |
2864 | createElement(Kind: Record.Kind); |
2865 | if (LVSymbol *Symbol = CurrentSymbol) { |
2866 | LVElement *BaseClass = getElement(StreamIdx: StreamTPI, TI: Base.getBaseType()); |
2867 | Symbol->setName(BaseClass->getName()); |
2868 | Symbol->setType(BaseClass); |
2869 | Symbol->setAccessibilityCode(Base.getAccess()); |
2870 | Symbol->setVirtualityCode(MethodKind::Virtual); |
2871 | static_cast<LVScope *>(Element)->addElement(Symbol); |
2872 | } |
2873 | |
2874 | return Error::success(); |
2875 | } |
2876 | |
2877 | Error LVLogicalVisitor::visitMemberRecord(CVMemberRecord &Record, |
2878 | TypeVisitorCallbacks &Callbacks, |
2879 | TypeIndex TI, LVElement *Element) { |
2880 | if (Error Err = Callbacks.visitMemberBegin(Record)) |
2881 | return Err; |
2882 | |
2883 | switch (Record.Kind) { |
2884 | default: |
2885 | if (Error Err = Callbacks.visitUnknownMember(Record)) |
2886 | return Err; |
2887 | break; |
2888 | #define MEMBER_RECORD(EnumName, EnumVal, Name) \ |
2889 | case EnumName: { \ |
2890 | if (Error Err = \ |
2891 | visitKnownMember<Name##Record>(Record, Callbacks, TI, Element)) \ |
2892 | return Err; \ |
2893 | break; \ |
2894 | } |
2895 | #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ |
2896 | MEMBER_RECORD(EnumVal, EnumVal, AliasName) |
2897 | #define TYPE_RECORD(EnumName, EnumVal, Name) |
2898 | #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) |
2899 | #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" |
2900 | } |
2901 | |
2902 | if (Error Err = Callbacks.visitMemberEnd(Record)) |
2903 | return Err; |
2904 | |
2905 | return Error::success(); |
2906 | } |
2907 | |
2908 | Error LVLogicalVisitor::finishVisitation(CVType &Record, TypeIndex TI, |
2909 | LVElement *Element) { |
2910 | switch (Record.kind()) { |
2911 | default: |
2912 | if (Error Err = visitUnknownType(Record, TI)) |
2913 | return Err; |
2914 | break; |
2915 | #define TYPE_RECORD(EnumName, EnumVal, Name) \ |
2916 | case EnumName: { \ |
2917 | if (Error Err = visitKnownRecord<Name##Record>(Record, TI, Element)) \ |
2918 | return Err; \ |
2919 | break; \ |
2920 | } |
2921 | #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ |
2922 | TYPE_RECORD(EnumVal, EnumVal, AliasName) |
2923 | #define MEMBER_RECORD(EnumName, EnumVal, Name) |
2924 | #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) |
2925 | #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" |
2926 | } |
2927 | |
2928 | return Error::success(); |
2929 | } |
2930 | |
2931 | // Customized version of 'FieldListVisitHelper'. |
2932 | Error LVLogicalVisitor::visitFieldListMemberStream( |
2933 | TypeIndex TI, LVElement *Element, ArrayRef<uint8_t> FieldList) { |
2934 | BinaryByteStream Stream(FieldList, llvm::endianness::little); |
2935 | BinaryStreamReader Reader(Stream); |
2936 | FieldListDeserializer Deserializer(Reader); |
2937 | TypeVisitorCallbackPipeline Pipeline; |
2938 | Pipeline.addCallbackToPipeline(Callbacks&: Deserializer); |
2939 | |
2940 | TypeLeafKind Leaf; |
2941 | while (!Reader.empty()) { |
2942 | if (Error Err = Reader.readEnum(Dest&: Leaf)) |
2943 | return Err; |
2944 | |
2945 | CVMemberRecord Record; |
2946 | Record.Kind = Leaf; |
2947 | if (Error Err = visitMemberRecord(Record, Callbacks&: Pipeline, TI, Element)) |
2948 | return Err; |
2949 | } |
2950 | |
2951 | return Error::success(); |
2952 | } |
2953 | |
2954 | void LVLogicalVisitor::addElement(LVScope *Scope, bool IsCompileUnit) { |
2955 | // The CodeView specifications does not treat S_COMPILE2 and S_COMPILE3 |
2956 | // as symbols that open a scope. The CodeView reader, treat them in a |
2957 | // similar way as DWARF. As there is no a symbole S_END to close the |
2958 | // compile unit, we need to check for the next compile unit. |
2959 | if (IsCompileUnit) { |
2960 | if (!ScopeStack.empty()) |
2961 | popScope(); |
2962 | InCompileUnitScope = true; |
2963 | } |
2964 | |
2965 | pushScope(Scope); |
2966 | ReaderParent->addElement(Scope); |
2967 | } |
2968 | |
2969 | void LVLogicalVisitor::addElement(LVSymbol *Symbol) { |
2970 | ReaderScope->addElement(Symbol); |
2971 | } |
2972 | |
2973 | void LVLogicalVisitor::addElement(LVType *Type) { |
2974 | ReaderScope->addElement(Type); |
2975 | } |
2976 | |
2977 | LVElement *LVLogicalVisitor::createElement(TypeLeafKind Kind) { |
2978 | CurrentScope = nullptr; |
2979 | CurrentSymbol = nullptr; |
2980 | CurrentType = nullptr; |
2981 | |
2982 | if (Kind < TypeIndex::FirstNonSimpleIndex) { |
2983 | CurrentType = Reader->createType(); |
2984 | CurrentType->setIsBase(); |
2985 | CurrentType->setTag(dwarf::DW_TAG_base_type); |
2986 | if (options().getAttributeBase()) |
2987 | CurrentType->setIncludeInPrint(); |
2988 | return CurrentType; |
2989 | } |
2990 | |
2991 | switch (Kind) { |
2992 | // Types. |
2993 | case TypeLeafKind::LF_ENUMERATE: |
2994 | CurrentType = Reader->createTypeEnumerator(); |
2995 | CurrentType->setTag(dwarf::DW_TAG_enumerator); |
2996 | return CurrentType; |
2997 | case TypeLeafKind::LF_MODIFIER: |
2998 | CurrentType = Reader->createType(); |
2999 | CurrentType->setIsModifier(); |
3000 | return CurrentType; |
3001 | case TypeLeafKind::LF_POINTER: |
3002 | CurrentType = Reader->createType(); |
3003 | CurrentType->setIsPointer(); |
3004 | CurrentType->setName("*" ); |
3005 | CurrentType->setTag(dwarf::DW_TAG_pointer_type); |
3006 | return CurrentType; |
3007 | |
3008 | // Symbols. |
3009 | case TypeLeafKind::LF_BCLASS: |
3010 | case TypeLeafKind::LF_IVBCLASS: |
3011 | case TypeLeafKind::LF_VBCLASS: |
3012 | CurrentSymbol = Reader->createSymbol(); |
3013 | CurrentSymbol->setTag(dwarf::DW_TAG_inheritance); |
3014 | CurrentSymbol->setIsInheritance(); |
3015 | return CurrentSymbol; |
3016 | case TypeLeafKind::LF_MEMBER: |
3017 | case TypeLeafKind::LF_STMEMBER: |
3018 | CurrentSymbol = Reader->createSymbol(); |
3019 | CurrentSymbol->setIsMember(); |
3020 | CurrentSymbol->setTag(dwarf::DW_TAG_member); |
3021 | return CurrentSymbol; |
3022 | |
3023 | // Scopes. |
3024 | case TypeLeafKind::LF_ARRAY: |
3025 | CurrentScope = Reader->createScopeArray(); |
3026 | CurrentScope->setTag(dwarf::DW_TAG_array_type); |
3027 | return CurrentScope; |
3028 | case TypeLeafKind::LF_CLASS: |
3029 | CurrentScope = Reader->createScopeAggregate(); |
3030 | CurrentScope->setTag(dwarf::DW_TAG_class_type); |
3031 | CurrentScope->setIsClass(); |
3032 | return CurrentScope; |
3033 | case TypeLeafKind::LF_ENUM: |
3034 | CurrentScope = Reader->createScopeEnumeration(); |
3035 | CurrentScope->setTag(dwarf::DW_TAG_enumeration_type); |
3036 | return CurrentScope; |
3037 | case TypeLeafKind::LF_METHOD: |
3038 | case TypeLeafKind::LF_ONEMETHOD: |
3039 | case TypeLeafKind::LF_PROCEDURE: |
3040 | CurrentScope = Reader->createScopeFunction(); |
3041 | CurrentScope->setIsSubprogram(); |
3042 | CurrentScope->setTag(dwarf::DW_TAG_subprogram); |
3043 | return CurrentScope; |
3044 | case TypeLeafKind::LF_STRUCTURE: |
3045 | CurrentScope = Reader->createScopeAggregate(); |
3046 | CurrentScope->setIsStructure(); |
3047 | CurrentScope->setTag(dwarf::DW_TAG_structure_type); |
3048 | return CurrentScope; |
3049 | case TypeLeafKind::LF_UNION: |
3050 | CurrentScope = Reader->createScopeAggregate(); |
3051 | CurrentScope->setIsUnion(); |
3052 | CurrentScope->setTag(dwarf::DW_TAG_union_type); |
3053 | return CurrentScope; |
3054 | default: |
3055 | // If '--internal=tag' and '--print=warning' are specified in the command |
3056 | // line, we record and print each seen 'TypeLeafKind'. |
3057 | break; |
3058 | } |
3059 | return nullptr; |
3060 | } |
3061 | |
3062 | LVElement *LVLogicalVisitor::createElement(SymbolKind Kind) { |
3063 | CurrentScope = nullptr; |
3064 | CurrentSymbol = nullptr; |
3065 | CurrentType = nullptr; |
3066 | switch (Kind) { |
3067 | // Types. |
3068 | case SymbolKind::S_UDT: |
3069 | CurrentType = Reader->createTypeDefinition(); |
3070 | CurrentType->setTag(dwarf::DW_TAG_typedef); |
3071 | return CurrentType; |
3072 | |
3073 | // Symbols. |
3074 | case SymbolKind::S_CONSTANT: |
3075 | CurrentSymbol = Reader->createSymbol(); |
3076 | CurrentSymbol->setIsConstant(); |
3077 | CurrentSymbol->setTag(dwarf::DW_TAG_constant); |
3078 | return CurrentSymbol; |
3079 | |
3080 | case SymbolKind::S_BPREL32: |
3081 | case SymbolKind::S_REGREL32: |
3082 | case SymbolKind::S_GDATA32: |
3083 | case SymbolKind::S_LDATA32: |
3084 | case SymbolKind::S_LOCAL: |
3085 | // During the symbol traversal more information is available to |
3086 | // determine if the symbol is a parameter or a variable. At this |
3087 | // stage mark it as variable. |
3088 | CurrentSymbol = Reader->createSymbol(); |
3089 | CurrentSymbol->setIsVariable(); |
3090 | CurrentSymbol->setTag(dwarf::DW_TAG_variable); |
3091 | return CurrentSymbol; |
3092 | |
3093 | // Scopes. |
3094 | case SymbolKind::S_BLOCK32: |
3095 | CurrentScope = Reader->createScope(); |
3096 | CurrentScope->setIsLexicalBlock(); |
3097 | CurrentScope->setTag(dwarf::DW_TAG_lexical_block); |
3098 | return CurrentScope; |
3099 | case SymbolKind::S_COMPILE2: |
3100 | case SymbolKind::S_COMPILE3: |
3101 | CurrentScope = Reader->createScopeCompileUnit(); |
3102 | CurrentScope->setTag(dwarf::DW_TAG_compile_unit); |
3103 | Reader->setCompileUnit(static_cast<LVScopeCompileUnit *>(CurrentScope)); |
3104 | return CurrentScope; |
3105 | case SymbolKind::S_INLINESITE: |
3106 | case SymbolKind::S_INLINESITE2: |
3107 | CurrentScope = Reader->createScopeFunctionInlined(); |
3108 | CurrentScope->setIsInlinedFunction(); |
3109 | CurrentScope->setTag(dwarf::DW_TAG_inlined_subroutine); |
3110 | return CurrentScope; |
3111 | case SymbolKind::S_LPROC32: |
3112 | case SymbolKind::S_GPROC32: |
3113 | case SymbolKind::S_LPROC32_ID: |
3114 | case SymbolKind::S_GPROC32_ID: |
3115 | case SymbolKind::S_SEPCODE: |
3116 | case SymbolKind::S_THUNK32: |
3117 | CurrentScope = Reader->createScopeFunction(); |
3118 | CurrentScope->setIsSubprogram(); |
3119 | CurrentScope->setTag(dwarf::DW_TAG_subprogram); |
3120 | return CurrentScope; |
3121 | default: |
3122 | // If '--internal=tag' and '--print=warning' are specified in the command |
3123 | // line, we record and print each seen 'SymbolKind'. |
3124 | break; |
3125 | } |
3126 | return nullptr; |
3127 | } |
3128 | |
3129 | LVElement *LVLogicalVisitor::createElement(TypeIndex TI, TypeLeafKind Kind) { |
3130 | LVElement *Element = Shared->TypeRecords.find(StreamIdx: StreamTPI, TI); |
3131 | if (!Element) { |
3132 | // We are dealing with a base type or pointer to a base type, which are |
3133 | // not included explicitly in the CodeView format. |
3134 | if (Kind < TypeIndex::FirstNonSimpleIndex) { |
3135 | Element = createElement(Kind); |
3136 | Element->setIsFinalized(); |
3137 | Shared->TypeRecords.add(StreamIdx: StreamTPI, TI: (TypeIndex)Kind, Kind, Element); |
3138 | Element->setOffset(Kind); |
3139 | return Element; |
3140 | } |
3141 | // We are dealing with a pointer to a base type. |
3142 | if (TI.getIndex() < TypeIndex::FirstNonSimpleIndex) { |
3143 | Element = createElement(Kind); |
3144 | Shared->TypeRecords.add(StreamIdx: StreamTPI, TI, Kind, Element); |
3145 | Element->setOffset(TI.getIndex()); |
3146 | Element->setOffsetFromTypeIndex(); |
3147 | return Element; |
3148 | } |
3149 | |
3150 | W.printString(Value: "** Not implemented. **" ); |
3151 | printTypeIndex(FieldName: "TypeIndex" , TI, StreamIdx: StreamTPI); |
3152 | W.printString(Label: "TypeLeafKind" , Value: formatTypeLeafKind(K: Kind)); |
3153 | return nullptr; |
3154 | } |
3155 | |
3156 | Element->setOffset(TI.getIndex()); |
3157 | Element->setOffsetFromTypeIndex(); |
3158 | return Element; |
3159 | } |
3160 | |
3161 | void LVLogicalVisitor::createDataMember(CVMemberRecord &Record, LVScope *Parent, |
3162 | StringRef Name, TypeIndex TI, |
3163 | MemberAccess Access) { |
3164 | LLVM_DEBUG({ |
3165 | printTypeIndex("TypeIndex" , TI, StreamTPI); |
3166 | W.printString("TypeName" , Name); |
3167 | }); |
3168 | |
3169 | createElement(Kind: Record.Kind); |
3170 | if (LVSymbol *Symbol = CurrentSymbol) { |
3171 | Symbol->setName(Name); |
3172 | if (TI.isNoneType() || TI.isSimple()) |
3173 | Symbol->setType(getElement(StreamIdx: StreamTPI, TI)); |
3174 | else { |
3175 | LazyRandomTypeCollection &Types = types(); |
3176 | CVType CVMemberType = Types.getType(Index: TI); |
3177 | if (CVMemberType.kind() == LF_BITFIELD) { |
3178 | if (Error Err = finishVisitation(Record&: CVMemberType, TI, Element: Symbol)) { |
3179 | consumeError(Err: std::move(Err)); |
3180 | return; |
3181 | } |
3182 | } else |
3183 | Symbol->setType(getElement(StreamIdx: StreamTPI, TI)); |
3184 | } |
3185 | Symbol->setAccessibilityCode(Access); |
3186 | Parent->addElement(Symbol); |
3187 | } |
3188 | } |
3189 | |
3190 | LVSymbol *LVLogicalVisitor::createParameter(LVElement *Element, StringRef Name, |
3191 | LVScope *Parent) { |
3192 | LVSymbol *Parameter = Reader->createSymbol(); |
3193 | Parent->addElement(Symbol: Parameter); |
3194 | Parameter->setIsParameter(); |
3195 | Parameter->setTag(dwarf::DW_TAG_formal_parameter); |
3196 | Parameter->setName(Name); |
3197 | Parameter->setType(Element); |
3198 | return Parameter; |
3199 | } |
3200 | |
3201 | LVSymbol *LVLogicalVisitor::createParameter(TypeIndex TI, StringRef Name, |
3202 | LVScope *Parent) { |
3203 | return createParameter(Element: getElement(StreamIdx: StreamTPI, TI), Name, Parent); |
3204 | } |
3205 | |
3206 | LVType *LVLogicalVisitor::createBaseType(TypeIndex TI, StringRef TypeName) { |
3207 | TypeLeafKind SimpleKind = (TypeLeafKind)TI.getSimpleKind(); |
3208 | TypeIndex TIR = (TypeIndex)SimpleKind; |
3209 | LLVM_DEBUG({ |
3210 | printTypeIndex("TypeIndex" , TIR, StreamTPI); |
3211 | W.printString("TypeName" , TypeName); |
3212 | }); |
3213 | |
3214 | if (LVElement *Element = Shared->TypeRecords.find(StreamIdx: StreamTPI, TI: TIR)) |
3215 | return static_cast<LVType *>(Element); |
3216 | |
3217 | if (createElement(TI: TIR, Kind: SimpleKind)) { |
3218 | CurrentType->setName(TypeName); |
3219 | CurrentType->setBitSize(getSizeInBytesForTypeIndex(TI: TIR) * DWARF_CHAR_BIT); |
3220 | Reader->getCompileUnit()->addElement(Type: CurrentType); |
3221 | } |
3222 | return CurrentType; |
3223 | } |
3224 | |
3225 | LVType *LVLogicalVisitor::createPointerType(TypeIndex TI, StringRef TypeName) { |
3226 | LLVM_DEBUG({ |
3227 | printTypeIndex("TypeIndex" , TI, StreamTPI); |
3228 | W.printString("TypeName" , TypeName); |
3229 | }); |
3230 | |
3231 | if (LVElement *Element = Shared->TypeRecords.find(StreamIdx: StreamTPI, TI)) |
3232 | return static_cast<LVType *>(Element); |
3233 | |
3234 | LVType *Pointee = createBaseType(TI, TypeName: TypeName.drop_back(N: 1)); |
3235 | if (createElement(TI, Kind: TypeLeafKind::LF_POINTER)) { |
3236 | CurrentType->setIsFinalized(); |
3237 | CurrentType->setType(Pointee); |
3238 | Reader->getCompileUnit()->addElement(Type: CurrentType); |
3239 | } |
3240 | return CurrentType; |
3241 | } |
3242 | |
3243 | void LVLogicalVisitor::createParents(StringRef ScopedName, LVElement *Element) { |
3244 | // For the given test case: |
3245 | // |
3246 | // struct S { enum E { ... }; }; |
3247 | // S::E V; |
3248 | // |
3249 | // 0 | S_LOCAL `V` |
3250 | // type=0x1004 (S::E), flags = none |
3251 | // 0x1004 | LF_ENUM `S::E` |
3252 | // options: has unique name | is nested |
3253 | // 0x1009 | LF_STRUCTURE `S` |
3254 | // options: contains nested class |
3255 | // |
3256 | // When the local 'V' is processed, its type 'E' is created. But There is |
3257 | // no direct reference to its parent 'S'. We use the scoped name for 'E', |
3258 | // to create its parents. |
3259 | |
3260 | // The input scoped name must have at least parent and nested names. |
3261 | // Drop the last element name, as it corresponds to the nested type. |
3262 | LVStringRefs Components = getAllLexicalComponents(Name: ScopedName); |
3263 | if (Components.size() < 2) |
3264 | return; |
3265 | Components.pop_back(); |
3266 | |
3267 | LVStringRefs::size_type FirstNamespace; |
3268 | LVStringRefs::size_type FirstAggregate; |
3269 | std::tie(args&: FirstNamespace, args&: FirstAggregate) = |
3270 | Shared->NamespaceDeduction.find(Components); |
3271 | |
3272 | LLVM_DEBUG({ |
3273 | W.printString("First Namespace" , Components[FirstNamespace]); |
3274 | W.printString("First NonNamespace" , Components[FirstAggregate]); |
3275 | }); |
3276 | |
3277 | // Create any referenced namespaces. |
3278 | if (FirstNamespace < FirstAggregate) { |
3279 | Shared->NamespaceDeduction.get( |
3280 | Components: LVStringRefs(Components.begin() + FirstNamespace, |
3281 | Components.begin() + FirstAggregate)); |
3282 | } |
3283 | |
3284 | // Traverse the enclosing scopes (aggregates) and create them. In the |
3285 | // case of nested empty aggregates, MSVC does not emit a full record |
3286 | // description. It emits only the reference record. |
3287 | LVScope *Aggregate = nullptr; |
3288 | TypeIndex TIAggregate; |
3289 | std::string AggregateName = getScopedName( |
3290 | Components: LVStringRefs(Components.begin(), Components.begin() + FirstAggregate)); |
3291 | |
3292 | // This traversal is executed at least once. |
3293 | for (LVStringRefs::size_type Index = FirstAggregate; |
3294 | Index < Components.size(); ++Index) { |
3295 | AggregateName = getScopedName(Components: LVStringRefs(Components.begin() + Index, |
3296 | Components.begin() + Index + 1), |
3297 | BaseName: AggregateName); |
3298 | TIAggregate = Shared->ForwardReferences.remap( |
3299 | TI: Shared->TypeRecords.find(StreamIdx: StreamTPI, Name: AggregateName)); |
3300 | Aggregate = |
3301 | TIAggregate.isNoneType() |
3302 | ? nullptr |
3303 | : static_cast<LVScope *>(getElement(StreamIdx: StreamTPI, TI: TIAggregate)); |
3304 | } |
3305 | |
3306 | // Workaround for cases where LF_NESTTYPE is missing for nested templates. |
3307 | // If we manage to get parent information from the scoped name, we can add |
3308 | // the nested type without relying on the LF_NESTTYPE. |
3309 | if (Aggregate && !Element->getIsScopedAlready()) { |
3310 | Aggregate->addElement(Element); |
3311 | Element->setIsScopedAlready(); |
3312 | } |
3313 | } |
3314 | |
3315 | LVElement *LVLogicalVisitor::getElement(uint32_t StreamIdx, TypeIndex TI, |
3316 | LVScope *Parent) { |
3317 | LLVM_DEBUG({ printTypeIndex("TypeIndex" , TI, StreamTPI); }); |
3318 | TI = Shared->ForwardReferences.remap(TI); |
3319 | LLVM_DEBUG({ printTypeIndex("TypeIndex Remap" , TI, StreamTPI); }); |
3320 | |
3321 | LVElement *Element = Shared->TypeRecords.find(StreamIdx, TI); |
3322 | if (!Element) { |
3323 | if (TI.isNoneType() || TI.isSimple()) { |
3324 | StringRef TypeName = TypeIndex::simpleTypeName(TI); |
3325 | // If the name ends with "*", create 2 logical types: a pointer and a |
3326 | // pointee type. TypeIndex is composed of a SympleTypeMode byte followed |
3327 | // by a SimpleTypeKind byte. The logical pointer will be identified by |
3328 | // the full TypeIndex value and the pointee by the SimpleTypeKind. |
3329 | return (TypeName.back() == '*') ? createPointerType(TI, TypeName) |
3330 | : createBaseType(TI, TypeName); |
3331 | } |
3332 | |
3333 | LLVM_DEBUG({ W.printHex("TypeIndex not implemented: " , TI.getIndex()); }); |
3334 | return nullptr; |
3335 | } |
3336 | |
3337 | // The element has been finalized. |
3338 | if (Element->getIsFinalized()) |
3339 | return Element; |
3340 | |
3341 | // Add the element in case of a given parent. |
3342 | if (Parent) |
3343 | Parent->addElement(Element); |
3344 | |
3345 | // Check for a composite type. |
3346 | LazyRandomTypeCollection &Types = types(); |
3347 | CVType CVRecord = Types.getType(Index: TI); |
3348 | if (Error Err = finishVisitation(Record&: CVRecord, TI, Element)) { |
3349 | consumeError(Err: std::move(Err)); |
3350 | return nullptr; |
3351 | } |
3352 | Element->setIsFinalized(); |
3353 | return Element; |
3354 | } |
3355 | |
3356 | void LVLogicalVisitor::processLines() { |
3357 | // Traverse the collected LF_UDT_SRC_LINE records and add the source line |
3358 | // information to the logical elements. |
3359 | for (const TypeIndex &Entry : Shared->LineRecords) { |
3360 | CVType CVRecord = ids().getType(Index: Entry); |
3361 | UdtSourceLineRecord Line; |
3362 | if (Error Err = TypeDeserializer::deserializeAs( |
3363 | CVT&: const_cast<CVType &>(CVRecord), Record&: Line)) |
3364 | consumeError(Err: std::move(Err)); |
3365 | else { |
3366 | LLVM_DEBUG({ |
3367 | printTypeIndex("UDT" , Line.getUDT(), StreamIPI); |
3368 | printTypeIndex("SourceFile" , Line.getSourceFile(), StreamIPI); |
3369 | W.printNumber("LineNumber" , Line.getLineNumber()); |
3370 | }); |
3371 | |
3372 | // The TypeIndex returned by 'getUDT()' must point to an already |
3373 | // created logical element. If no logical element is found, it means |
3374 | // the LF_UDT_SRC_LINE is associated with a system TypeIndex. |
3375 | if (LVElement *Element = Shared->TypeRecords.find( |
3376 | StreamIdx: StreamTPI, TI: Line.getUDT(), /*Create=*/false)) { |
3377 | Element->setLineNumber(Line.getLineNumber()); |
3378 | Element->setFilenameIndex( |
3379 | Shared->StringRecords.findIndex(TI: Line.getSourceFile())); |
3380 | } |
3381 | } |
3382 | } |
3383 | } |
3384 | |
3385 | void LVLogicalVisitor::processNamespaces() { |
3386 | // Create namespaces. |
3387 | Shared->NamespaceDeduction.init(); |
3388 | } |
3389 | |
3390 | void LVLogicalVisitor::processFiles() { Shared->StringRecords.addFilenames(); } |
3391 | |
3392 | void LVLogicalVisitor::printRecords(raw_ostream &OS) const { |
3393 | if (!options().getInternalTag()) |
3394 | return; |
3395 | |
3396 | unsigned Count = 0; |
3397 | auto PrintItem = [&](StringRef Name) { |
3398 | auto NewLine = [&]() { |
3399 | if (++Count == 4) { |
3400 | Count = 0; |
3401 | OS << "\n" ; |
3402 | } |
3403 | }; |
3404 | OS << format(Fmt: "%20s" , Vals: Name.str().c_str()); |
3405 | NewLine(); |
3406 | }; |
3407 | |
3408 | OS << "\nTypes:\n" ; |
3409 | for (const TypeLeafKind &Kind : Shared->TypeKinds) |
3410 | PrintItem(formatTypeLeafKind(K: Kind)); |
3411 | Shared->TypeKinds.clear(); |
3412 | |
3413 | Count = 0; |
3414 | OS << "\nSymbols:\n" ; |
3415 | for (const SymbolKind &Kind : Shared->SymbolKinds) |
3416 | PrintItem(LVCodeViewReader::getSymbolKindName(Kind)); |
3417 | Shared->SymbolKinds.clear(); |
3418 | |
3419 | OS << "\n" ; |
3420 | } |
3421 | |
3422 | Error LVLogicalVisitor::inlineSiteAnnotation(LVScope *AbstractFunction, |
3423 | LVScope *InlinedFunction, |
3424 | InlineSiteSym &InlineSite) { |
3425 | // Get the parent scope to update the address ranges of the nested |
3426 | // scope representing the inlined function. |
3427 | LVAddress ParentLowPC = 0; |
3428 | LVScope *Parent = InlinedFunction->getParentScope(); |
3429 | if (const LVLocations *Locations = Parent->getRanges()) { |
3430 | if (!Locations->empty()) |
3431 | ParentLowPC = (*Locations->begin())->getLowerAddress(); |
3432 | } |
3433 | |
3434 | // For the given inlinesite, get the initial line number and its |
3435 | // source filename. Update the logical scope representing it. |
3436 | uint32_t LineNumber = 0; |
3437 | StringRef Filename; |
3438 | LVInlineeInfo::iterator Iter = InlineeInfo.find(x: InlineSite.Inlinee); |
3439 | if (Iter != InlineeInfo.end()) { |
3440 | LineNumber = Iter->second.first; |
3441 | Filename = Iter->second.second; |
3442 | AbstractFunction->setLineNumber(LineNumber); |
3443 | // TODO: This part needs additional work in order to set properly the |
3444 | // correct filename in order to detect changes between filenames. |
3445 | // AbstractFunction->setFilename(Filename); |
3446 | } |
3447 | |
3448 | LLVM_DEBUG({ |
3449 | dbgs() << "inlineSiteAnnotation\n" |
3450 | << "Abstract: " << AbstractFunction->getName() << "\n" |
3451 | << "Inlined: " << InlinedFunction->getName() << "\n" |
3452 | << "Parent: " << Parent->getName() << "\n" |
3453 | << "Low PC: " << hexValue(ParentLowPC) << "\n" ; |
3454 | }); |
3455 | |
3456 | // Get the source lines if requested by command line option. |
3457 | if (!options().getPrintLines()) |
3458 | return Error::success(); |
3459 | |
3460 | // Limitation: Currently we don't track changes in the FileOffset. The |
3461 | // side effects are the caller that it is unable to differentiate the |
3462 | // source filename for the inlined code. |
3463 | uint64_t CodeOffset = ParentLowPC; |
3464 | int32_t LineOffset = LineNumber; |
3465 | uint32_t FileOffset = 0; |
3466 | |
3467 | auto UpdateClose = [&]() { LLVM_DEBUG({ dbgs() << ("\n" ); }); }; |
3468 | auto UpdateCodeOffset = [&](uint32_t Delta) { |
3469 | CodeOffset += Delta; |
3470 | LLVM_DEBUG({ |
3471 | dbgs() << formatv(" code 0x{0} (+0x{1})" , utohexstr(CodeOffset), |
3472 | utohexstr(Delta)); |
3473 | }); |
3474 | }; |
3475 | auto UpdateLineOffset = [&](int32_t Delta) { |
3476 | LineOffset += Delta; |
3477 | LLVM_DEBUG({ |
3478 | char Sign = Delta > 0 ? '+' : '-'; |
3479 | dbgs() << formatv(" line {0} ({1}{2})" , LineOffset, Sign, |
3480 | std::abs(Delta)); |
3481 | }); |
3482 | }; |
3483 | auto UpdateFileOffset = [&](int32_t Offset) { |
3484 | FileOffset = Offset; |
3485 | LLVM_DEBUG({ dbgs() << formatv(" file {0}" , FileOffset); }); |
3486 | }; |
3487 | |
3488 | LVLines InlineeLines; |
3489 | auto CreateLine = [&]() { |
3490 | // Create the logical line record. |
3491 | LVLineDebug *Line = Reader->createLineDebug(); |
3492 | Line->setAddress(CodeOffset); |
3493 | Line->setLineNumber(LineOffset); |
3494 | // TODO: This part needs additional work in order to set properly the |
3495 | // correct filename in order to detect changes between filenames. |
3496 | // Line->setFilename(Filename); |
3497 | InlineeLines.push_back(Elt: Line); |
3498 | }; |
3499 | |
3500 | bool SeenLowAddress = false; |
3501 | bool SeenHighAddress = false; |
3502 | uint64_t LowPC = 0; |
3503 | uint64_t HighPC = 0; |
3504 | |
3505 | for (auto &Annot : InlineSite.annotations()) { |
3506 | LLVM_DEBUG({ |
3507 | dbgs() << formatv(" {0}" , |
3508 | fmt_align(toHex(Annot.Bytes), AlignStyle::Left, 9)); |
3509 | }); |
3510 | |
3511 | // Use the opcode to interpret the integer values. |
3512 | switch (Annot.OpCode) { |
3513 | case BinaryAnnotationsOpCode::ChangeCodeOffset: |
3514 | case BinaryAnnotationsOpCode::CodeOffset: |
3515 | case BinaryAnnotationsOpCode::ChangeCodeLength: |
3516 | UpdateCodeOffset(Annot.U1); |
3517 | UpdateClose(); |
3518 | if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeOffset) { |
3519 | CreateLine(); |
3520 | LowPC = CodeOffset; |
3521 | SeenLowAddress = true; |
3522 | break; |
3523 | } |
3524 | if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeLength) { |
3525 | HighPC = CodeOffset - 1; |
3526 | SeenHighAddress = true; |
3527 | } |
3528 | break; |
3529 | case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: |
3530 | UpdateCodeOffset(Annot.U2); |
3531 | UpdateClose(); |
3532 | break; |
3533 | case BinaryAnnotationsOpCode::ChangeLineOffset: |
3534 | case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: |
3535 | UpdateCodeOffset(Annot.U1); |
3536 | UpdateLineOffset(Annot.S1); |
3537 | UpdateClose(); |
3538 | if (Annot.OpCode == |
3539 | BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset) |
3540 | CreateLine(); |
3541 | break; |
3542 | case BinaryAnnotationsOpCode::ChangeFile: |
3543 | UpdateFileOffset(Annot.U1); |
3544 | UpdateClose(); |
3545 | break; |
3546 | default: |
3547 | break; |
3548 | } |
3549 | if (SeenLowAddress && SeenHighAddress) { |
3550 | SeenLowAddress = false; |
3551 | SeenHighAddress = false; |
3552 | InlinedFunction->addObject(LowerAddress: LowPC, UpperAddress: HighPC); |
3553 | } |
3554 | } |
3555 | |
3556 | Reader->addInlineeLines(Scope: InlinedFunction, Lines&: InlineeLines); |
3557 | UpdateClose(); |
3558 | |
3559 | return Error::success(); |
3560 | } |
3561 | |