LLVM  17.0.0git
LVReader.cpp
Go to the documentation of this file.
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 
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.
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 //===----------------------------------------------------------------------===//
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 
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 
155  if (CurrentReader)
156  return *CurrentReader;
157  outs() << "Invalid instance reader.\n";
158  llvm_unreachable("Invalid instance reader.");
159 }
160 void LVReader::setInstance(LVReader *Reader) { CurrentReader = Reader; }
161 
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.
185  if (CompileUnits.size()) {
186  // Get Compile Unit for the given object.
187  LVCompileUnits::const_iterator Iter =
188  std::prev(CompileUnits.lower_bound(Object->getOffset()));
189  if (Iter != CompileUnits.end())
190  return Iter->second->getFilename(Index);
191  }
192 
193  return CompileUnit ? CompileUnit->getFilename(Index) : StringRef();
194 }
195 
196 // The Reader is the module that creates the logical view using the debug
197 // information contained in the binary file specified in the command line.
198 // This is the main entry point for the Reader and performs the following
199 // steps:
200 // - Process any patterns collected from the '--select' options.
201 // - For each compile unit in the debug information:
202 // * Create the logical elements (scopes, symbols, types, lines).
203 // * Collect debug ranges and debug locations.
204 // * Move the collected logical lines to their associated scopes.
205 // - Once all the compile units have been processed, traverse the scopes
206 // tree in order to:
207 // * Calculate symbol coverage.
208 // * Detect invalid ranges and locations.
209 // * "resolve" the logical elements. During this pass, the names and
210 // file information are updated, to reflect any dependency with other
211 // logical elements.
213  // Set current Reader instance.
214  setInstance(this);
215 
216  // Before any scopes creation, process any pattern specified by the
217  // --select and --select-offsets options.
220 
221  // Add any specific element printing requests based on the element kind.
222  patterns().addRequest(options().Select.Elements);
223  patterns().addRequest(options().Select.Lines);
224  patterns().addRequest(options().Select.Scopes);
225  patterns().addRequest(options().Select.Symbols);
226  patterns().addRequest(options().Select.Types);
227 
228  // Once we have processed the requests for any particular kind of elements,
229  // we need to update the report options, in order to have a default value.
231 
232  // Delegate the scope tree creation to the specific reader.
233  if (Error Err = createScopes())
234  return Err;
235 
236  if (options().getInternalIntegrity() && !checkIntegrityScopesTree(Root))
237  return llvm::make_error<StringError>("Duplicated elements in Scopes Tree",
239 
240  // Calculate symbol coverage and detect invalid debug locations and ranges.
242 
243  // As the elements can depend on elements from a different compile unit,
244  // information such as name and file/line source information needs to be
245  // updated.
247 
248  sortScopes();
249  return Error::success();
250 }
251 
252 // Default handler for a generic reader.
254  // Set current Reader instance.
255  setInstance(this);
256 
257  // Check for any '--report' request.
258  if (options().getReportExecute()) {
259  // Requested details.
260  if (options().getReportList())
261  if (Error Err = printMatchedElements(/*UseMatchedElements=*/true))
262  return Err;
263  // Requested only children.
264  if (options().getReportChildren() && !options().getReportParents())
265  if (Error Err = printMatchedElements(/*UseMatchedElements=*/false))
266  return Err;
267  // Requested (parents) or (parents and children).
268  if (options().getReportParents() || options().getReportView())
269  if (Error Err = printScopes())
270  return Err;
271 
272  return Error::success();
273  }
274 
275  return printScopes();
276 }
277 
279  if (bool DoPrint =
280  (options().getPrintExecute() || options().getComparePrint())) {
281  if (Error Err = createSplitFolder())
282  return Err;
283 
284  // Start printing from the root.
285  bool DoMatch = options().getSelectGenericPattern() ||
286  options().getSelectGenericKind() ||
287  options().getSelectOffsetPattern();
288  return Root->doPrint(OutputSplit, DoMatch, DoPrint, OS);
289  }
290 
291  return Error::success();
292 }
293 
294 Error LVReader::printMatchedElements(bool UseMatchedElements) {
295  if (Error Err = createSplitFolder())
296  return Err;
297 
298  return Root->doPrintMatches(OutputSplit, OS, UseMatchedElements);
299 }
300 
301 void LVReader::print(raw_ostream &OS) const {
302  OS << "LVReader\n";
303  LLVM_DEBUG(dbgs() << "PrintReader\n");
304 }
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::logicalview::LVScopeRoot::processRangeInformation
void processRangeInformation()
Definition: LVScope.cpp:2020
llvm::logicalview::LVSplitContext::createSplitFolder
Error createSplitFolder(StringRef Where)
Definition: LVReader.cpp:113
FileSystem.h
llvm::sys::fs::OF_None
@ OF_None
Definition: FileSystem.h:757
llvm::logicalview::LVReader::doPrint
Error doPrint()
Definition: LVReader.cpp:253
CurrentReader
LVReader * CurrentReader
Definition: LVReader.cpp:153
llvm::SmallVector< LVScope *, 8 >
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
llvm::logicalview::LVObject::getID
uint64_t getID() const
Definition: LVObject.h:337
llvm::sys::path::end
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:235
llvm::sys::path::begin
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:226
LVScope.h
llvm::logicalview::LVScope::getTypes
const LVTypes * getTypes() const
Definition: LVScope.h:209
llvm::logicalview::LVElement::getName
StringRef getName() const override
Definition: LVElement.h:185
llvm::logicalview::LVScope::doPrint
Error doPrint(bool Split, bool Match, bool Print, raw_ostream &OS, bool Full=true) const override
Definition: LVScope.cpp:595
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::formatv
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: FormatVariadic.h:251
checkIntegrityScopesTree
bool checkIntegrityScopesTree(LVScope *Root)
Definition: LVReader.cpp:29
llvm::outs
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
Definition: raw_ostream.cpp:883
llvm::logicalview::LVReader::getInstance
static LVReader & getInstance()
Definition: LVReader.cpp:154
l
This requires reassociating to forms of expressions that are already something that reassoc doesn t think about yet These two functions should generate the same code on big endian int * l
Definition: README.txt:100
llvm::dwarf::Index
Index
Definition: Dwarf.h:550
First
into llvm powi allowing the code generator to produce balanced multiplication trees First
Definition: README.txt:54
llvm::logicalview::LVScopeRoot::doPrintMatches
Error doPrintMatches(bool Split, raw_ostream &OS, bool UseMatchedElements) const
Definition: LVScope.cpp:2049
llvm::sys::fs::create_directories
std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
Definition: Path.cpp:967
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
llvm::logicalview::LVObject
Definition: LVObject.h:124
FormatVariadic.h
llvm::SmallString< 128 >
llvm::OutputFileType::Object
@ Object
llvm::logicalview::LVReader::print
void print(raw_ostream &OS) const
Definition: LVReader.cpp:301
llvm::logicalview::LVCompareKind::Scopes
@ Scopes
llvm::logicalview::LVReader::createScopes
virtual Error createScopes()
Definition: LVReader.h:94
Index
uint32_t Index
Definition: ELFObjHandler.cpp:83
llvm::logicalview::patterns
LVPatterns & patterns()
Definition: LVOptions.h:640
llvm::CompileUnit
Stores all information relating to a compile unit, be it in its original instance in the object file ...
Definition: DWARFLinkerCompileUnit.h:48
llvm::fmt_repeat
detail::RepeatAdapter< T > fmt_repeat(T &&Item, size_t Count)
Definition: FormatAdapters.h:97
llvm::logicalview::LVSplitContext::getLocation
std::string getLocation() const
Definition: LVReader.h:53
llvm::logicalview::LVReader::printMatchedElements
virtual Error printMatchedElements(bool UseMatchedElements)
Definition: LVReader.cpp:294
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::logicalview::LVReader::doLoad
Error doLoad()
Definition: LVReader.cpp:212
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:82
llvm::sys::fs::make_absolute
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:906
llvm::logicalview::LVInternalKind::Integrity
@ Integrity
llvm::logicalview::LVReader
Definition: LVReader.h:57
llvm::logicalview::LVElement
Definition: LVElement.h:68
llvm::logicalview::flattenedFilePath
std::string flattenedFilePath(StringRef Path)
Definition: LVSupport.cpp:44
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::logicalview::LVReader::printScopes
virtual Error printScopes()
Definition: LVReader.cpp:278
llvm::logicalview::LVPatterns::updateReportOptions
void updateReportOptions()
Definition: LVOptions.cpp:490
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::logicalview::LVPatterns::addOffsetPatterns
void addOffsetPatterns(const LVOffsetSet &Patterns)
Definition: LVOptions.cpp:447
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::logicalview::LVScope::getSymbols
const LVSymbols * getSymbols() const
Definition: LVScope.h:208
llvm::MCID::Select
@ Select
Definition: MCInstrDesc.h:165
llvm::logicalview::LVScope
Definition: LVScope.h:74
llvm::logicalview::LVPatterns::addGenericPatterns
void addGenericPatterns(StringSet<> &Patterns)
Definition: LVOptions.cpp:439
llvm::stable_sort
void stable_sort(R &&Range)
Definition: STLExtras.h:1948
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1246
llvm::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
llvm::logicalview::LVScope::resolveElements
void resolveElements()
Definition: LVScope.cpp:454
llvm::logicalview::LVObject::kind
virtual const char * kind() const
Definition: LVObject.h:294
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
LVLine.h
llvm::logicalview::LVReader::OS
raw_ostream & OS
Definition: LVReader.h:82
llvm::logicalview::LVScope::getLines
const LVLines * getLines() const
Definition: LVScope.h:205
llvm::logicalview::LVSplitContext::open
std::error_code open(std::string Name, std::string Extension, raw_ostream &OS)
Definition: LVReader.cpp:132
FormatAdapters.h
llvm::logicalview::LVReader::Root
LVScopeRoot * Root
Definition: LVReader.h:78
llvm::logicalview::LVScope::getScopes
const LVScopes * getScopes() const
Definition: LVScope.h:207
LVReader.h
llvm::logicalview::LVReader::getFilename
StringRef getFilename() const
Definition: LVReader.h:138
llvm::logicalview::options
LVOptions & options()
Definition: LVOptions.h:445
llvm::logicalview
Definition: LVCompare.h:20
llvm::logicalview::LVReader::sortScopes
virtual void sortScopes()
Definition: LVReader.h:121
llvm::logicalview::LVReader::setInstance
static void setInstance(LVReader *Reader)
Definition: LVReader.cpp:160