1 //===-- LVReader.h ----------------------------------------------*- C++ -*-===//
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 file defines the LVReader class, which is used to describe a debug
10 // information reader.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVREADER_H
15 #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVREADER_H
16
17 #include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
18 #include "llvm/DebugInfo/LogicalView/Core/LVRange.h"
19 #include "llvm/Support/Errc.h"
20 #include "llvm/Support/Error.h"
21 #include "llvm/Support/ScopedPrinter.h"
22 #include "llvm/Support/ToolOutputFile.h"
23 #include <map>
24
25 namespace llvm {
26 namespace logicalview {
27
28 constexpr LVSectionIndex UndefinedSectionIndex = 0;
29
30 class LVScopeCompileUnit;
31 class LVObject;
32
33 class LVSplitContext final {
34 std::unique_ptr<ToolOutputFile> OutputFile;
35 std::string Location;
36
37 public:
38 LVSplitContext() = default;
39 LVSplitContext(const LVSplitContext &) = delete;
40 LVSplitContext &operator=(const LVSplitContext &) = delete;
41 ~LVSplitContext() = default;
42
43 Error createSplitFolder(StringRef Where);
44 std::error_code open(std::string Name, std::string Extension,
45 raw_ostream &OS);
close()46 void close() {
47 if (OutputFile) {
48 OutputFile->os().close();
49 OutputFile = nullptr;
50 }
51 }
52
getLocation()53 std::string getLocation() const { return Location; }
os()54 raw_fd_ostream &os() { return OutputFile->os(); }
55 };
56
57 class LVReader {
58 LVBinaryType BinaryType;
59
60 // Context used by '--output=split' command line option.
61 LVSplitContext SplitContext;
62
63 // Compile Units DIE Offset => Scope.
64 using LVCompileUnits = std::map<LVOffset, LVScopeCompileUnit *>;
65 LVCompileUnits CompileUnits;
66
67 // Added elements to be used during elements comparison.
68 LVLines Lines;
69 LVScopes Scopes;
70 LVSymbols Symbols;
71 LVTypes Types;
72
73 // Create split folder.
74 Error createSplitFolder();
75 bool OutputSplit = false;
76
77 protected:
78 LVScopeRoot *Root = nullptr;
79 std::string InputFilename;
80 std::string FileFormatName;
81 ScopedPrinter &W;
82 raw_ostream &OS;
83 LVScopeCompileUnit *CompileUnit = nullptr;
84
85 // Only for ELF format. The CodeView is handled in a different way.
86 LVSectionIndex DotTextSectionIndex = UndefinedSectionIndex;
87
88 // Record Compilation Unit entry.
addCompileUnitOffset(LVOffset Offset,LVScopeCompileUnit * CompileUnit)89 void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) {
90 CompileUnits.emplace(Offset, CompileUnit);
91 }
92
93 // Create the Scope Root.
createScopes()94 virtual Error createScopes() {
95 Root = new LVScopeRoot();
96 Root->setName(getFilename());
97 if (options().getAttributeFormat())
98 Root->setFileFormatName(FileFormatName);
99 return Error::success();
100 }
101
102 // Return a pathname composed by: parent_path(InputFilename)/filename(From).
103 // This is useful when a type server (PDB file associated with an object
104 // file or a precompiled header file) or a DWARF split object have been
105 // moved from their original location. That is the case when running
106 // regression tests, where object files are created in one location and
107 // executed in a different location.
createAlternativePath(StringRef From)108 std::string createAlternativePath(StringRef From) {
109 // During the reader initialization, any backslashes in 'InputFilename'
110 // are converted to forward slashes.
111 SmallString<128> Path;
112 sys::path::append(Path, sys::path::Style::posix,
113 sys::path::parent_path(InputFilename),
114 sys::path::filename(sys::path::convert_to_slash(
115 From, sys::path::Style::windows)));
116 return std::string(Path);
117 }
118
119 virtual Error printScopes();
120 virtual Error printMatchedElements(bool UseMatchedElements);
sortScopes()121 virtual void sortScopes() {}
122
123 public:
124 LVReader() = delete;
125 LVReader(StringRef InputFilename, StringRef FileFormatName, ScopedPrinter &W,
126 LVBinaryType BinaryType = LVBinaryType::NONE)
BinaryType(BinaryType)127 : BinaryType(BinaryType), OutputSplit(options().getOutputSplit()),
128 InputFilename(InputFilename), FileFormatName(FileFormatName), W(W),
129 OS(W.getOStream()) {}
130 LVReader(const LVReader &) = delete;
131 LVReader &operator=(const LVReader &) = delete;
~LVReader()132 virtual ~LVReader() {
133 if (Root)
134 delete Root;
135 }
136
137 StringRef getFilename(LVObject *Object, size_t Index) const;
getFilename()138 StringRef getFilename() const { return InputFilename; }
setFilename(std::string Name)139 void setFilename(std::string Name) { InputFilename = std::move(Name); }
getFileFormatName()140 StringRef getFileFormatName() const { return FileFormatName; }
141
outputStream()142 raw_ostream &outputStream() { return OS; }
143
isBinaryTypeNone()144 bool isBinaryTypeNone() const { return BinaryType == LVBinaryType::NONE; }
isBinaryTypeELF()145 bool isBinaryTypeELF() const { return BinaryType == LVBinaryType::ELF; }
isBinaryTypeCOFF()146 bool isBinaryTypeCOFF() const { return BinaryType == LVBinaryType::COFF; }
147
getCompileUnit()148 LVScopeCompileUnit *getCompileUnit() const { return CompileUnit; }
setCompileUnit(LVScope * Scope)149 void setCompileUnit(LVScope *Scope) {
150 assert(Scope && Scope->isCompileUnit() && "Scope is not a compile unit");
151 CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
152 }
153
154 // Access to the scopes root.
getScopesRoot()155 LVScopeRoot *getScopesRoot() const { return Root; }
156
157 Error doPrint();
158 Error doLoad();
159
getRegisterName(LVSmall Opcode,uint64_t Operands[2])160 virtual std::string getRegisterName(LVSmall Opcode, uint64_t Operands[2]) {
161 llvm_unreachable("Invalid instance reader.");
162 return {};
163 }
164
getDotTextSectionIndex()165 LVSectionIndex getDotTextSectionIndex() const { return DotTextSectionIndex; }
getSectionIndex(LVScope * Scope)166 virtual LVSectionIndex getSectionIndex(LVScope *Scope) {
167 return getDotTextSectionIndex();
168 }
169
170 virtual bool isSystemEntry(LVElement *Element, StringRef Name = {}) const {
171 return false;
172 };
173
174 // Access to split context.
getSplitContext()175 LVSplitContext &getSplitContext() { return SplitContext; }
176
177 // In the case of element comparison, register that added element.
notifyAddedElement(LVLine * Line)178 void notifyAddedElement(LVLine *Line) {
179 if (!options().getCompareContext() && options().getCompareLines())
180 Lines.push_back(Line);
181 }
notifyAddedElement(LVScope * Scope)182 void notifyAddedElement(LVScope *Scope) {
183 if (!options().getCompareContext() && options().getCompareScopes())
184 Scopes.push_back(Scope);
185 }
notifyAddedElement(LVSymbol * Symbol)186 void notifyAddedElement(LVSymbol *Symbol) {
187 if (!options().getCompareContext() && options().getCompareSymbols())
188 Symbols.push_back(Symbol);
189 }
notifyAddedElement(LVType * Type)190 void notifyAddedElement(LVType *Type) {
191 if (!options().getCompareContext() && options().getCompareTypes())
192 Types.push_back(Type);
193 }
194
getLines()195 const LVLines &getLines() const { return Lines; }
getScopes()196 const LVScopes &getScopes() const { return Scopes; }
getSymbols()197 const LVSymbols &getSymbols() const { return Symbols; }
getTypes()198 const LVTypes &getTypes() const { return Types; }
199
200 // Conditions to print an object.
doPrintLine(const LVLine * Line)201 bool doPrintLine(const LVLine *Line) const {
202 return patterns().printElement(Line);
203 }
doPrintLocation(const LVLocation * Location)204 bool doPrintLocation(const LVLocation *Location) const {
205 return patterns().printObject(Location);
206 }
doPrintScope(const LVScope * Scope)207 bool doPrintScope(const LVScope *Scope) const {
208 return patterns().printElement(Scope);
209 }
doPrintSymbol(const LVSymbol * Symbol)210 bool doPrintSymbol(const LVSymbol *Symbol) const {
211 return patterns().printElement(Symbol);
212 }
doPrintType(const LVType * Type)213 bool doPrintType(const LVType *Type) const {
214 return patterns().printElement(Type);
215 }
216
217 static LVReader &getInstance();
218 static void setInstance(LVReader *Reader);
219
220 void print(raw_ostream &OS) const;
printRecords(raw_ostream & OS)221 virtual void printRecords(raw_ostream &OS) const {}
222
223 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()224 void dump() const { print(dbgs()); }
225 #endif
226 };
227
getReader()228 inline LVReader &getReader() { return LVReader::getInstance(); }
getReaderSplitContext()229 inline LVSplitContext &getReaderSplitContext() {
230 return getReader().getSplitContext();
231 }
getReaderCompileUnit()232 inline LVScopeCompileUnit *getReaderCompileUnit() {
233 return getReader().getCompileUnit();
234 }
235
236 } // end namespace logicalview
237 } // end namespace llvm
238
239 #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVREADER_H
240