1//===-- LVReader.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 LVReader class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
14#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
15#include "llvm/Support/FileSystem.h"
16#include "llvm/Support/FormatAdapters.h"
17#include "llvm/Support/FormatVariadic.h"
18#include <tuple>
19
20using namespace llvm;
21using namespace llvm::logicalview;
22
23#define DEBUG_TYPE "Reader"
24
25// Detect elements that are inserted more than once at different scopes,
26// causing a crash on the reader destruction, as the element is already
27// deleted from other scope. Helper for CodeView reader.
28bool checkIntegrityScopesTree(LVScope *Root) {
29 using LVDuplicateEntry = std::tuple<LVElement *, LVScope *, LVScope *>;
30 using LVDuplicate = std::vector<LVDuplicateEntry>;
31 LVDuplicate Duplicate;
32
33 using LVIntegrity = std::map<LVElement *, LVScope *>;
34 LVIntegrity Integrity;
35
36 // Add the given element to the integrity map.
37 auto AddElement = [&](LVElement *Element, LVScope *Scope) {
38 LVIntegrity::iterator Iter = Integrity.find(x: Element);
39 if (Iter == Integrity.end())
40 Integrity.emplace(args&: Element, args&: Scope);
41 else
42 // We found a duplicate.
43 Duplicate.emplace_back(args&: Element, args&: Scope, args&: Iter->second);
44 };
45
46 // Recursively add all the elements in the scope.
47 std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
48 auto Traverse = [&](const auto *Set) {
49 if (Set)
50 for (const auto &Entry : *Set)
51 AddElement(Entry, Parent);
52 };
53 if (const LVScopes *Scopes = Parent->getScopes()) {
54 for (LVScope *Scope : *Scopes) {
55 AddElement(Scope, Parent);
56 TraverseScope(Scope);
57 }
58 }
59 Traverse(Parent->getSymbols());
60 Traverse(Parent->getTypes());
61 Traverse(Parent->getLines());
62 };
63
64 // Start traversing the scopes root and print any duplicates.
65 TraverseScope(Root);
66 bool PassIntegrity = true;
67 if (Duplicate.size()) {
68 llvm::stable_sort(Range&: Duplicate, C: [](const auto &l, const auto &r) {
69 return std::get<0>(l)->getID() < std::get<0>(r)->getID();
70 });
71
72 auto PrintIndex = [](unsigned Index) {
73 if (Index)
74 dbgs() << format(Fmt: "%8d: ", Vals: Index);
75 else
76 dbgs() << format(Fmt: "%8c: ", Vals: ' ');
77 };
78 auto PrintElement = [&](LVElement *Element, unsigned Index = 0) {
79 PrintIndex(Index);
80 std::string ElementName(Element->getName());
81 dbgs() << format(Fmt: "%15s ID=0x%08x '%s'\n", Vals: Element->kind(),
82 Vals: Element->getID(), Vals: ElementName.c_str());
83 };
84
85 std::string RootName(Root->getName());
86 dbgs() << formatv(Fmt: "{0}\n", Vals: fmt_repeat(Item: '=', Count: 72));
87 dbgs() << format(Fmt: "Root: '%s'\nDuplicated elements: %d\n", Vals: RootName.c_str(),
88 Vals: Duplicate.size());
89 dbgs() << formatv(Fmt: "{0}\n", Vals: fmt_repeat(Item: '=', Count: 72));
90
91 unsigned Index = 0;
92 for (const LVDuplicateEntry &Entry : Duplicate) {
93 LVElement *Element;
94 LVScope *First;
95 LVScope *Second;
96 std::tie(args&: Element, args&: First, args&: Second) = Entry;
97 dbgs() << formatv(Fmt: "\n{0}\n", Vals: fmt_repeat(Item: '-', Count: 72));
98 PrintElement(Element, ++Index);
99 PrintElement(First);
100 PrintElement(Second);
101 dbgs() << formatv(Fmt: "{0}\n", Vals: fmt_repeat(Item: '-', Count: 72));
102 }
103 PassIntegrity = false;
104 }
105 return PassIntegrity;
106}
107
108//===----------------------------------------------------------------------===//
109// Class to represent a split context.
110//===----------------------------------------------------------------------===//
111Error LVSplitContext::createSplitFolder(StringRef Where) {
112 // The 'location' will represent the root directory for the output created
113 // by the context. It will contain the different CUs files, that will be
114 // extracted from a single ELF.
115 Location = std::string(Where);
116
117 // Add a trailing slash, if there is none.
118 size_t Pos = Location.find_last_of(c: '/');
119 if (Location.length() != Pos + 1)
120 Location.append(s: "/");
121
122 // Make sure the new directory exists, creating it if necessary.
123 if (std::error_code EC = llvm::sys::fs::create_directories(path: Location))
124 return createStringError(EC, Fmt: "Error: could not create directory %s",
125 Vals: Location.c_str());
126
127 return Error::success();
128}
129
130std::error_code LVSplitContext::open(std::string ContextName,
131 std::string Extension, raw_ostream &OS) {
132 assert(OutputFile == nullptr && "OutputFile already set.");
133
134 // Transforms '/', '\', '.', ':' into '_'.
135 std::string Name(flattenedFilePath(Path: ContextName));
136 Name.append(str: Extension);
137 // Add the split context location folder name.
138 if (!Location.empty())
139 Name.insert(pos1: 0, str: Location);
140
141 std::error_code EC;
142 OutputFile = std::make_unique<ToolOutputFile>(args&: Name, args&: EC, args: sys::fs::OF_None);
143 if (EC)
144 return EC;
145
146 // Don't remove output file.
147 OutputFile->keep();
148 return std::error_code();
149}
150
151LVReader *CurrentReader = nullptr;
152LVReader &LVReader::getInstance() {
153 if (CurrentReader)
154 return *CurrentReader;
155 outs() << "Invalid instance reader.\n";
156 llvm_unreachable("Invalid instance reader.");
157}
158void LVReader::setInstance(LVReader *Reader) { CurrentReader = Reader; }
159
160Error LVReader::createSplitFolder() {
161 if (OutputSplit) {
162 // If the '--output=split' was specified, but no '--split-folder'
163 // option, use the input file as base for the split location.
164 if (options().getOutputFolder().empty())
165 options().setOutputFolder(getFilename().str() + "_cus");
166
167 SmallString<128> SplitFolder;
168 SplitFolder = options().getOutputFolder();
169 sys::fs::make_absolute(path&: SplitFolder);
170
171 // Return error if unable to create a split context location.
172 if (Error Err = SplitContext.createSplitFolder(Where: SplitFolder))
173 return Err;
174
175 OS << "\nSplit View Location: '" << SplitContext.getLocation() << "'\n";
176 }
177
178 return Error::success();
179}
180
181// Get the filename for given object.
182StringRef LVReader::getFilename(LVObject *Object, size_t Index) const {
183 // TODO: The current CodeView Reader implementation does not have support
184 // for multiple compile units. Until we have a proper offset calculation,
185 // check only in the current compile unit.
186 if (CompileUnits.size()) {
187 // Get Compile Unit for the given object.
188 LVCompileUnits::const_iterator Iter =
189 std::prev(x: CompileUnits.lower_bound(x: Object->getOffset()));
190 if (Iter != CompileUnits.end())
191 return Iter->second->getFilename(Index);
192 }
193
194 return CompileUnit ? CompileUnit->getFilename(Index) : StringRef();
195}
196
197void LVReader::addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope) {
198 LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
199 ScopesWithRanges->addEntry(Scope);
200}
201
202void LVReader::addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope,
203 LVAddress LowerAddress, LVAddress UpperAddress) {
204 LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
205 ScopesWithRanges->addEntry(Scope, LowerAddress, UpperAddress);
206}
207
208LVRange *LVReader::getSectionRanges(LVSectionIndex SectionIndex) {
209 // Check if we already have a mapping for this section index.
210 LVSectionRanges::iterator IterSection = SectionRanges.find(x: SectionIndex);
211 if (IterSection == SectionRanges.end())
212 IterSection =
213 SectionRanges.emplace(args&: SectionIndex, args: std::make_unique<LVRange>()).first;
214 LVRange *Range = IterSection->second.get();
215 assert(Range && "Range is null.");
216 return Range;
217}
218
219LVElement *LVReader::createElement(dwarf::Tag Tag) {
220 CurrentScope = nullptr;
221 CurrentSymbol = nullptr;
222 CurrentType = nullptr;
223 CurrentRanges.clear();
224
225 LLVM_DEBUG(
226 { dbgs() << "\n[createElement] " << dwarf::TagString(Tag) << "\n"; });
227
228 if (!options().getPrintSymbols()) {
229 switch (Tag) {
230 // As the command line options did not specify a request to print
231 // logical symbols (--print=symbols or --print=all or --print=elements),
232 // skip its creation.
233 case dwarf::DW_TAG_formal_parameter:
234 case dwarf::DW_TAG_unspecified_parameters:
235 case dwarf::DW_TAG_member:
236 case dwarf::DW_TAG_variable:
237 case dwarf::DW_TAG_inheritance:
238 case dwarf::DW_TAG_constant:
239 case dwarf::DW_TAG_call_site_parameter:
240 case dwarf::DW_TAG_GNU_call_site_parameter:
241 return nullptr;
242 default:
243 break;
244 }
245 }
246
247 switch (Tag) {
248 // Types.
249 case dwarf::DW_TAG_base_type:
250 CurrentType = createType();
251 CurrentType->setIsBase();
252 if (options().getAttributeBase())
253 CurrentType->setIncludeInPrint();
254 return CurrentType;
255 case dwarf::DW_TAG_const_type:
256 CurrentType = createType();
257 CurrentType->setIsConst();
258 CurrentType->setName("const");
259 return CurrentType;
260 case dwarf::DW_TAG_enumerator:
261 CurrentType = createTypeEnumerator();
262 return CurrentType;
263 case dwarf::DW_TAG_imported_declaration:
264 CurrentType = createTypeImport();
265 CurrentType->setIsImportDeclaration();
266 return CurrentType;
267 case dwarf::DW_TAG_imported_module:
268 CurrentType = createTypeImport();
269 CurrentType->setIsImportModule();
270 return CurrentType;
271 case dwarf::DW_TAG_pointer_type:
272 CurrentType = createType();
273 CurrentType->setIsPointer();
274 CurrentType->setName("*");
275 return CurrentType;
276 case dwarf::DW_TAG_ptr_to_member_type:
277 CurrentType = createType();
278 CurrentType->setIsPointerMember();
279 CurrentType->setName("*");
280 return CurrentType;
281 case dwarf::DW_TAG_reference_type:
282 CurrentType = createType();
283 CurrentType->setIsReference();
284 CurrentType->setName("&");
285 return CurrentType;
286 case dwarf::DW_TAG_restrict_type:
287 CurrentType = createType();
288 CurrentType->setIsRestrict();
289 CurrentType->setName("restrict");
290 return CurrentType;
291 case dwarf::DW_TAG_rvalue_reference_type:
292 CurrentType = createType();
293 CurrentType->setIsRvalueReference();
294 CurrentType->setName("&&");
295 return CurrentType;
296 case dwarf::DW_TAG_subrange_type:
297 CurrentType = createTypeSubrange();
298 return CurrentType;
299 case dwarf::DW_TAG_template_value_parameter:
300 CurrentType = createTypeParam();
301 CurrentType->setIsTemplateValueParam();
302 return CurrentType;
303 case dwarf::DW_TAG_template_type_parameter:
304 CurrentType = createTypeParam();
305 CurrentType->setIsTemplateTypeParam();
306 return CurrentType;
307 case dwarf::DW_TAG_GNU_template_template_param:
308 CurrentType = createTypeParam();
309 CurrentType->setIsTemplateTemplateParam();
310 return CurrentType;
311 case dwarf::DW_TAG_typedef:
312 CurrentType = createTypeDefinition();
313 return CurrentType;
314 case dwarf::DW_TAG_unspecified_type:
315 CurrentType = createType();
316 CurrentType->setIsUnspecified();
317 return CurrentType;
318 case dwarf::DW_TAG_volatile_type:
319 CurrentType = createType();
320 CurrentType->setIsVolatile();
321 CurrentType->setName("volatile");
322 return CurrentType;
323
324 // Symbols.
325 case dwarf::DW_TAG_formal_parameter:
326 CurrentSymbol = createSymbol();
327 CurrentSymbol->setIsParameter();
328 return CurrentSymbol;
329 case dwarf::DW_TAG_unspecified_parameters:
330 CurrentSymbol = createSymbol();
331 CurrentSymbol->setIsUnspecified();
332 CurrentSymbol->setName("...");
333 return CurrentSymbol;
334 case dwarf::DW_TAG_member:
335 CurrentSymbol = createSymbol();
336 CurrentSymbol->setIsMember();
337 return CurrentSymbol;
338 case dwarf::DW_TAG_variable:
339 CurrentSymbol = createSymbol();
340 CurrentSymbol->setIsVariable();
341 return CurrentSymbol;
342 case dwarf::DW_TAG_inheritance:
343 CurrentSymbol = createSymbol();
344 CurrentSymbol->setIsInheritance();
345 return CurrentSymbol;
346 case dwarf::DW_TAG_call_site_parameter:
347 case dwarf::DW_TAG_GNU_call_site_parameter:
348 CurrentSymbol = createSymbol();
349 CurrentSymbol->setIsCallSiteParameter();
350 return CurrentSymbol;
351 case dwarf::DW_TAG_constant:
352 CurrentSymbol = createSymbol();
353 CurrentSymbol->setIsConstant();
354 return CurrentSymbol;
355
356 // Scopes.
357 case dwarf::DW_TAG_catch_block:
358 CurrentScope = createScope();
359 CurrentScope->setIsCatchBlock();
360 return CurrentScope;
361 case dwarf::DW_TAG_lexical_block:
362 CurrentScope = createScope();
363 CurrentScope->setIsLexicalBlock();
364 return CurrentScope;
365 case dwarf::DW_TAG_try_block:
366 CurrentScope = createScope();
367 CurrentScope->setIsTryBlock();
368 return CurrentScope;
369 case dwarf::DW_TAG_compile_unit:
370 case dwarf::DW_TAG_skeleton_unit:
371 CurrentScope = createScopeCompileUnit();
372 CompileUnit = static_cast<LVScopeCompileUnit *>(CurrentScope);
373 return CurrentScope;
374 case dwarf::DW_TAG_inlined_subroutine:
375 CurrentScope = createScopeFunctionInlined();
376 return CurrentScope;
377 case dwarf::DW_TAG_namespace:
378 CurrentScope = createScopeNamespace();
379 return CurrentScope;
380 case dwarf::DW_TAG_template_alias:
381 CurrentScope = createScopeAlias();
382 return CurrentScope;
383 case dwarf::DW_TAG_array_type:
384 CurrentScope = createScopeArray();
385 return CurrentScope;
386 case dwarf::DW_TAG_call_site:
387 case dwarf::DW_TAG_GNU_call_site:
388 CurrentScope = createScopeFunction();
389 CurrentScope->setIsCallSite();
390 return CurrentScope;
391 case dwarf::DW_TAG_entry_point:
392 CurrentScope = createScopeFunction();
393 CurrentScope->setIsEntryPoint();
394 return CurrentScope;
395 case dwarf::DW_TAG_subprogram:
396 CurrentScope = createScopeFunction();
397 CurrentScope->setIsSubprogram();
398 return CurrentScope;
399 case dwarf::DW_TAG_subroutine_type:
400 CurrentScope = createScopeFunctionType();
401 return CurrentScope;
402 case dwarf::DW_TAG_label:
403 CurrentScope = createScopeFunction();
404 CurrentScope->setIsLabel();
405 return CurrentScope;
406 case dwarf::DW_TAG_class_type:
407 CurrentScope = createScopeAggregate();
408 CurrentScope->setIsClass();
409 return CurrentScope;
410 case dwarf::DW_TAG_structure_type:
411 CurrentScope = createScopeAggregate();
412 CurrentScope->setIsStructure();
413 return CurrentScope;
414 case dwarf::DW_TAG_union_type:
415 CurrentScope = createScopeAggregate();
416 CurrentScope->setIsUnion();
417 return CurrentScope;
418 case dwarf::DW_TAG_enumeration_type:
419 CurrentScope = createScopeEnumeration();
420 return CurrentScope;
421 case dwarf::DW_TAG_GNU_formal_parameter_pack:
422 CurrentScope = createScopeFormalPack();
423 return CurrentScope;
424 case dwarf::DW_TAG_GNU_template_parameter_pack:
425 CurrentScope = createScopeTemplatePack();
426 return CurrentScope;
427 case dwarf::DW_TAG_module:
428 CurrentScope = createScopeModule();
429 return CurrentScope;
430 default:
431 // Collect TAGs not implemented.
432 if (options().getInternalTag() && Tag)
433 CompileUnit->addDebugTag(Target: Tag, Offset: CurrentOffset);
434 break;
435 }
436
437 LLVM_DEBUG({
438 dbgs() << "DWARF Tag not implemented: " << dwarf::TagString(Tag) << "\n";
439 });
440
441 return nullptr;
442}
443
444// The Reader is the module that creates the logical view using the debug
445// information contained in the binary file specified in the command line.
446// This is the main entry point for the Reader and performs the following
447// steps:
448// - Process any patterns collected from the '--select' options.
449// - For each compile unit in the debug information:
450// * Create the logical elements (scopes, symbols, types, lines).
451// * Collect debug ranges and debug locations.
452// * Move the collected logical lines to their associated scopes.
453// - Once all the compile units have been processed, traverse the scopes
454// tree in order to:
455// * Calculate symbol coverage.
456// * Detect invalid ranges and locations.
457// * "resolve" the logical elements. During this pass, the names and
458// file information are updated, to reflect any dependency with other
459// logical elements.
460Error LVReader::doLoad() {
461 // Set current Reader instance.
462 setInstance(this);
463
464 // Before any scopes creation, process any pattern specified by the
465 // --select and --select-offsets options.
466 patterns().addGenericPatterns(Patterns&: options().Select.Generic);
467 patterns().addOffsetPatterns(Patterns: options().Select.Offsets);
468
469 // Add any specific element printing requests based on the element kind.
470 patterns().addRequest(Selection&: options().Select.Elements);
471 patterns().addRequest(Selection&: options().Select.Lines);
472 patterns().addRequest(Selection&: options().Select.Scopes);
473 patterns().addRequest(Selection&: options().Select.Symbols);
474 patterns().addRequest(Selection&: options().Select.Types);
475
476 // Once we have processed the requests for any particular kind of elements,
477 // we need to update the report options, in order to have a default value.
478 patterns().updateReportOptions();
479
480 // Delegate the scope tree creation to the specific reader.
481 if (Error Err = createScopes())
482 return Err;
483
484 if (options().getInternalIntegrity() && !checkIntegrityScopesTree(Root))
485 return llvm::make_error<StringError>(Args: "Duplicated elements in Scopes Tree",
486 Args: inconvertibleErrorCode());
487
488 // Calculate symbol coverage and detect invalid debug locations and ranges.
489 Root->processRangeInformation();
490
491 // As the elements can depend on elements from a different compile unit,
492 // information such as name and file/line source information needs to be
493 // updated.
494 Root->resolveElements();
495
496 sortScopes();
497 return Error::success();
498}
499
500// Default handler for a generic reader.
501Error LVReader::doPrint() {
502 // Set current Reader instance.
503 setInstance(this);
504
505 // Check for any '--report' request.
506 if (options().getReportExecute()) {
507 // Requested details.
508 if (options().getReportList())
509 if (Error Err = printMatchedElements(/*UseMatchedElements=*/true))
510 return Err;
511 // Requested only children.
512 if (options().getReportChildren() && !options().getReportParents())
513 if (Error Err = printMatchedElements(/*UseMatchedElements=*/false))
514 return Err;
515 // Requested (parents) or (parents and children).
516 if (options().getReportParents() || options().getReportView())
517 if (Error Err = printScopes())
518 return Err;
519
520 return Error::success();
521 }
522
523 return printScopes();
524}
525
526Error LVReader::printScopes() {
527 if (bool DoPrint =
528 (options().getPrintExecute() || options().getComparePrint())) {
529 if (Error Err = createSplitFolder())
530 return Err;
531
532 // Start printing from the root.
533 bool DoMatch = options().getSelectGenericPattern() ||
534 options().getSelectGenericKind() ||
535 options().getSelectOffsetPattern();
536 return Root->doPrint(Split: OutputSplit, Match: DoMatch, Print: DoPrint, OS);
537 }
538
539 return Error::success();
540}
541
542Error LVReader::printMatchedElements(bool UseMatchedElements) {
543 if (Error Err = createSplitFolder())
544 return Err;
545
546 return Root->doPrintMatches(Split: OutputSplit, OS, UseMatchedElements);
547}
548
549void LVReader::print(raw_ostream &OS) const {
550 OS << "LVReader\n";
551 LLVM_DEBUG(dbgs() << "PrintReader\n");
552}
553