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/LVLine.h"
15 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/FormatAdapters.h"
18 #include "llvm/Support/FormatVariadic.h"
19 #include <tuple>
20 
21 using namespace llvm;
22 using namespace llvm::logicalview;
23 
24 #define DEBUG_TYPE "Reader"
25 
26 // Detect elements that are inserted more than once at different scopes,
27 // causing a crash on the reader destruction, as the element is already
28 // deleted from other scope. Helper for CodeView reader.
checkIntegrityScopesTree(LVScope * Root)29 bool checkIntegrityScopesTree(LVScope *Root) {
30   using LVDuplicateEntry = std::tuple<LVElement *, LVScope *, LVScope *>;
31   using LVDuplicate = std::vector<LVDuplicateEntry>;
32   LVDuplicate Duplicate;
33 
34   using LVIntegrity = std::map<LVElement *, LVScope *>;
35   LVIntegrity Integrity;
36 
37   // Add the given element to the integrity map.
38   auto AddElement = [&](LVElement *Element, LVScope *Scope) {
39     LVIntegrity::iterator Iter = Integrity.find(Element);
40     if (Iter == Integrity.end())
41       Integrity.emplace(Element, Scope);
42     else
43       // We found a duplicate.
44       Duplicate.emplace_back(Element, Scope, Iter->second);
45   };
46 
47   // Recursively add all the elements in the scope.
48   std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
49     auto Traverse = [&](const auto *Set) {
50       if (Set)
51         for (const auto &Entry : *Set)
52           AddElement(Entry, Parent);
53     };
54     if (const LVScopes *Scopes = Parent->getScopes()) {
55       for (LVScope *Scope : *Scopes) {
56         AddElement(Scope, Parent);
57         TraverseScope(Scope);
58       }
59     }
60     Traverse(Parent->getSymbols());
61     Traverse(Parent->getTypes());
62     Traverse(Parent->getLines());
63   };
64 
65   // Start traversing the scopes root and print any duplicates.
66   TraverseScope(Root);
67   bool PassIntegrity = true;
68   if (Duplicate.size()) {
69     std::stable_sort(begin(Duplicate), end(Duplicate),
70                      [](const auto &l, const auto &r) {
71                        return std::get<0>(l)->getID() < std::get<0>(r)->getID();
72                      });
73 
74     auto PrintIndex = [](unsigned Index) {
75       if (Index)
76         dbgs() << format("%8d: ", Index);
77       else
78         dbgs() << format("%8c: ", ' ');
79     };
80     auto PrintElement = [&](LVElement *Element, unsigned Index = 0) {
81       PrintIndex(Index);
82       std::string ElementName(Element->getName());
83       dbgs() << format("%15s ID=0x%08x '%s'\n", Element->kind(),
84                        Element->getID(), ElementName.c_str());
85     };
86 
87     std::string RootName(Root->getName());
88     dbgs() << formatv("{0}\n", fmt_repeat('=', 72));
89     dbgs() << format("Root: '%s'\nDuplicated elements: %d\n", RootName.c_str(),
90                      Duplicate.size());
91     dbgs() << formatv("{0}\n", fmt_repeat('=', 72));
92 
93     unsigned Index = 0;
94     for (const LVDuplicateEntry &Entry : Duplicate) {
95       LVElement *Element;
96       LVScope *First;
97       LVScope *Second;
98       std::tie(Element, First, Second) = Entry;
99       dbgs() << formatv("\n{0}\n", fmt_repeat('-', 72));
100       PrintElement(Element, ++Index);
101       PrintElement(First);
102       PrintElement(Second);
103       dbgs() << formatv("{0}\n", fmt_repeat('-', 72));
104     }
105     PassIntegrity = false;
106   }
107   return PassIntegrity;
108 }
109 
110 //===----------------------------------------------------------------------===//
111 // Class to represent a split context.
112 //===----------------------------------------------------------------------===//
createSplitFolder(StringRef Where)113 Error LVSplitContext::createSplitFolder(StringRef Where) {
114   // The 'location' will represent the root directory for the output created
115   // by the context. It will contain the different CUs files, that will be
116   // extracted from a single ELF.
117   Location = std::string(Where);
118 
119   // Add a trailing slash, if there is none.
120   size_t Pos = Location.find_last_of('/');
121   if (Location.length() != Pos + 1)
122     Location.append("/");
123 
124   // Make sure the new directory exists, creating it if necessary.
125   if (std::error_code EC = llvm::sys::fs::create_directories(Location))
126     return createStringError(EC, "Error: could not create directory %s",
127                              Location.c_str());
128 
129   return Error::success();
130 }
131 
open(std::string ContextName,std::string Extension,raw_ostream & OS)132 std::error_code LVSplitContext::open(std::string ContextName,
133                                      std::string Extension, raw_ostream &OS) {
134   assert(OutputFile == nullptr && "OutputFile already set.");
135 
136   // Transforms '/', '\', '.', ':' into '_'.
137   std::string Name(flattenedFilePath(ContextName));
138   Name.append(Extension);
139   // Add the split context location folder name.
140   if (!Location.empty())
141     Name.insert(0, Location);
142 
143   std::error_code EC;
144   OutputFile = std::make_unique<ToolOutputFile>(Name, EC, sys::fs::OF_None);
145   if (EC)
146     return EC;
147 
148   // Don't remove output file.
149   OutputFile->keep();
150   return std::error_code();
151 }
152 
153 LVReader *CurrentReader = nullptr;
getInstance()154 LVReader &LVReader::getInstance() {
155   if (CurrentReader)
156     return *CurrentReader;
157   outs() << "Invalid instance reader.\n";
158   llvm_unreachable("Invalid instance reader.");
159 }
setInstance(LVReader * Reader)160 void LVReader::setInstance(LVReader *Reader) { CurrentReader = Reader; }
161 
createSplitFolder()162 Error LVReader::createSplitFolder() {
163   if (OutputSplit) {
164     // If the '--output=split' was specified, but no '--split-folder'
165     // option, use the input file as base for the split location.
166     if (options().getOutputFolder().empty())
167       options().setOutputFolder(getFilename().str() + "_cus");
168 
169     SmallString<128> SplitFolder;
170     SplitFolder = options().getOutputFolder();
171     sys::fs::make_absolute(SplitFolder);
172 
173     // Return error if unable to create a split context location.
174     if (Error Err = SplitContext.createSplitFolder(SplitFolder))
175       return Err;
176 
177     OS << "\nSplit View Location: '" << SplitContext.getLocation() << "'\n";
178   }
179 
180   return Error::success();
181 }
182 
183 // Get the filename for given object.
getFilename(LVObject * Object,size_t Index) const184 StringRef LVReader::getFilename(LVObject *Object, size_t Index) const {
185   // TODO: The current CodeView Reader implementation does not have support
186   // for multiple compile units. Until we have a proper offset calculation,
187   // check only in the current compile unit.
188   if (CompileUnits.size()) {
189     // Get Compile Unit for the given object.
190     LVCompileUnits::const_iterator Iter =
191         std::prev(CompileUnits.lower_bound(Object->getOffset()));
192     if (Iter != CompileUnits.end())
193       return Iter->second->getFilename(Index);
194   }
195 
196   return CompileUnit ? CompileUnit->getFilename(Index) : StringRef();
197 }
198 
199 // The Reader is the module that creates the logical view using the debug
200 // information contained in the binary file specified in the command line.
201 // This is the main entry point for the Reader and performs the following
202 // steps:
203 // - Process any patterns collected from the '--select' options.
204 // - For each compile unit in the debug information:
205 //   * Create the logical elements (scopes, symbols, types, lines).
206 //   * Collect debug ranges and debug locations.
207 //   * Move the collected logical lines to their associated scopes.
208 // - Once all the compile units have been processed, traverse the scopes
209 //   tree in order to:
210 //   * Calculate symbol coverage.
211 //   * Detect invalid ranges and locations.
212 //   * "resolve" the logical elements. During this pass, the names and
213 //      file information are updated, to reflect any dependency with other
214 //     logical elements.
doLoad()215 Error LVReader::doLoad() {
216   // Set current Reader instance.
217   setInstance(this);
218 
219   // Before any scopes creation, process any pattern specified by the
220   // --select and --select-offsets options.
221   patterns().addGenericPatterns(options().Select.Generic);
222   patterns().addOffsetPatterns(options().Select.Offsets);
223 
224   // Add any specific element printing requests based on the element kind.
225   patterns().addRequest(options().Select.Elements);
226   patterns().addRequest(options().Select.Lines);
227   patterns().addRequest(options().Select.Scopes);
228   patterns().addRequest(options().Select.Symbols);
229   patterns().addRequest(options().Select.Types);
230 
231   // Once we have processed the requests for any particular kind of elements,
232   // we need to update the report options, in order to have a default value.
233   patterns().updateReportOptions();
234 
235   // Delegate the scope tree creation to the specific reader.
236   if (Error Err = createScopes())
237     return Err;
238 
239   if (options().getInternalIntegrity() && !checkIntegrityScopesTree(Root))
240     return llvm::make_error<StringError>("Duplicated elements in Scopes Tree",
241                                          inconvertibleErrorCode());
242 
243   // Calculate symbol coverage and detect invalid debug locations and ranges.
244   Root->processRangeInformation();
245 
246   // As the elements can depend on elements from a different compile unit,
247   // information such as name and file/line source information needs to be
248   // updated.
249   Root->resolveElements();
250 
251   sortScopes();
252   return Error::success();
253 }
254 
255 // Default handler for a generic reader.
doPrint()256 Error LVReader::doPrint() {
257   // Set current Reader instance.
258   setInstance(this);
259 
260   // Check for any '--report' request.
261   if (options().getReportExecute()) {
262     // Requested details.
263     if (options().getReportList())
264       if (Error Err = printMatchedElements(/*UseMatchedElements=*/true))
265         return Err;
266     // Requested only children.
267     if (options().getReportChildren() && !options().getReportParents())
268       if (Error Err = printMatchedElements(/*UseMatchedElements=*/false))
269         return Err;
270     // Requested (parents) or (parents and children).
271     if (options().getReportParents() || options().getReportView())
272       if (Error Err = printScopes())
273         return Err;
274 
275     return Error::success();
276   }
277 
278   return printScopes();
279 }
280 
printScopes()281 Error LVReader::printScopes() {
282   if (bool DoPrint =
283           (options().getPrintExecute() || options().getComparePrint())) {
284     if (Error Err = createSplitFolder())
285       return Err;
286 
287     // Start printing from the root.
288     bool DoMatch = options().getSelectGenericPattern() ||
289                    options().getSelectGenericKind() ||
290                    options().getSelectOffsetPattern();
291     return Root->doPrint(OutputSplit, DoMatch, DoPrint, OS);
292   }
293 
294   return Error::success();
295 }
296 
printMatchedElements(bool UseMatchedElements)297 Error LVReader::printMatchedElements(bool UseMatchedElements) {
298   if (Error Err = createSplitFolder())
299     return Err;
300 
301   return Root->doPrintMatches(OutputSplit, OS, UseMatchedElements);
302 }
303 
print(raw_ostream & OS) const304 void LVReader::print(raw_ostream &OS) const {
305   OS << "LVReader\n";
306   LLVM_DEBUG(dbgs() << "PrintReader\n");
307 }
308