xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
20 using namespace llvm;
21 using 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.
checkIntegrityScopesTree(LVScope * Root)28 bool 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(Element);
39     if (Iter == Integrity.end())
40       Integrity.emplace(Element, Scope);
41     else
42       // We found a duplicate.
43       Duplicate.emplace_back(Element, Scope, 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(Duplicate, [](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("%8d: ", Index);
75       else
76         dbgs() << format("%8c: ", ' ');
77     };
78     auto PrintElement = [&](LVElement *Element, unsigned Index = 0) {
79       PrintIndex(Index);
80       std::string ElementName(Element->getName());
81       dbgs() << format("%15s ID=0x%08x '%s'\n", Element->kind(),
82                        Element->getID(), ElementName.c_str());
83     };
84 
85     std::string RootName(Root->getName());
86     dbgs() << formatv("{0}\n", fmt_repeat('=', 72));
87     dbgs() << format("Root: '%s'\nDuplicated elements: %d\n", RootName.c_str(),
88                      Duplicate.size());
89     dbgs() << formatv("{0}\n", fmt_repeat('=', 72));
90 
91     unsigned Index = 0;
92     for (const LVDuplicateEntry &Entry : Duplicate) {
93       LVElement *Element;
94       LVScope *First;
95       LVScope *Second;
96       std::tie(Element, First, Second) = Entry;
97       dbgs() << formatv("\n{0}\n", fmt_repeat('-', 72));
98       PrintElement(Element, ++Index);
99       PrintElement(First);
100       PrintElement(Second);
101       dbgs() << formatv("{0}\n", fmt_repeat('-', 72));
102     }
103     PassIntegrity = false;
104   }
105   return PassIntegrity;
106 }
107 
108 //===----------------------------------------------------------------------===//
109 // Class to represent a split context.
110 //===----------------------------------------------------------------------===//
createSplitFolder(StringRef Where)111 Error 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('/');
119   if (Location.length() != Pos + 1)
120     Location.append("/");
121 
122   // Make sure the new directory exists, creating it if necessary.
123   if (std::error_code EC = llvm::sys::fs::create_directories(Location))
124     return createStringError(EC, "Error: could not create directory %s",
125                              Location.c_str());
126 
127   return Error::success();
128 }
129 
open(std::string ContextName,std::string Extension,raw_ostream & OS)130 std::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(ContextName));
136   Name.append(Extension);
137   // Add the split context location folder name.
138   if (!Location.empty())
139     Name.insert(0, Location);
140 
141   std::error_code EC;
142   OutputFile = std::make_unique<ToolOutputFile>(Name, EC, 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 
151 LVReader *CurrentReader = nullptr;
getInstance()152 LVReader &LVReader::getInstance() {
153   if (CurrentReader)
154     return *CurrentReader;
155   outs() << "Invalid instance reader.\n";
156   llvm_unreachable("Invalid instance reader.");
157 }
setInstance(LVReader * Reader)158 void LVReader::setInstance(LVReader *Reader) { CurrentReader = Reader; }
159 
createSplitFolder()160 Error 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(SplitFolder);
170 
171     // Return error if unable to create a split context location.
172     if (Error Err = SplitContext.createSplitFolder(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.
getFilename(LVObject * Object,size_t Index) const182 StringRef 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(CompileUnits.lower_bound(Object->getOffset()));
190     if (Iter != CompileUnits.end())
191       return Iter->second->getFilename(Index);
192   }
193 
194   return CompileUnit ? CompileUnit->getFilename(Index) : StringRef();
195 }
196 
addSectionRange(LVSectionIndex SectionIndex,LVScope * Scope)197 void LVReader::addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope) {
198   LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
199   ScopesWithRanges->addEntry(Scope);
200 }
201 
addSectionRange(LVSectionIndex SectionIndex,LVScope * Scope,LVAddress LowerAddress,LVAddress UpperAddress)202 void LVReader::addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope,
203                                LVAddress LowerAddress, LVAddress UpperAddress) {
204   LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
205   ScopesWithRanges->addEntry(Scope, LowerAddress, UpperAddress);
206 }
207 
getSectionRanges(LVSectionIndex SectionIndex)208 LVRange *LVReader::getSectionRanges(LVSectionIndex SectionIndex) {
209   // Check if we already have a mapping for this section index.
210   LVSectionRanges::iterator IterSection = SectionRanges.find(SectionIndex);
211   if (IterSection == SectionRanges.end())
212     IterSection =
213         SectionRanges.emplace(SectionIndex, std::make_unique<LVRange>()).first;
214   LVRange *Range = IterSection->second.get();
215   assert(Range && "Range is null.");
216   return Range;
217 }
218 
createElement(dwarf::Tag Tag)219 LVElement *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(Tag, 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.
doLoad()460 Error 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(options().Select.Generic);
467   patterns().addOffsetPatterns(options().Select.Offsets);
468 
469   // Add any specific element printing requests based on the element kind.
470   patterns().addRequest(options().Select.Elements);
471   patterns().addRequest(options().Select.Lines);
472   patterns().addRequest(options().Select.Scopes);
473   patterns().addRequest(options().Select.Symbols);
474   patterns().addRequest(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>("Duplicated elements in Scopes Tree",
486                                          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.
doPrint()501 Error 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 
printScopes()526 Error 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(OutputSplit, DoMatch, DoPrint, OS);
537   }
538 
539   return Error::success();
540 }
541 
printMatchedElements(bool UseMatchedElements)542 Error LVReader::printMatchedElements(bool UseMatchedElements) {
543   if (Error Err = createSplitFolder())
544     return Err;
545 
546   return Root->doPrintMatches(OutputSplit, OS, UseMatchedElements);
547 }
548 
print(raw_ostream & OS) const549 void LVReader::print(raw_ostream &OS) const {
550   OS << "LVReader\n";
551   LLVM_DEBUG(dbgs() << "PrintReader\n");
552 }
553