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