Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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); |
||
46 | void close() { |
||
47 | if (OutputFile) { |
||
48 | OutputFile->os().close(); |
||
49 | OutputFile = nullptr; |
||
50 | } |
||
51 | } |
||
52 | |||
53 | std::string getLocation() const { return Location; } |
||
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. |
||
89 | void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) { |
||
90 | CompileUnits.emplace(Offset, CompileUnit); |
||
91 | } |
||
92 | |||
93 | // Create the Scope Root. |
||
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. |
||
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); |
||
121 | virtual void sortScopes() {} |
||
122 | |||
123 | public: |
||
124 | LVReader() = delete; |
||
125 | LVReader(StringRef InputFilename, StringRef FileFormatName, ScopedPrinter &W, |
||
126 | LVBinaryType BinaryType = LVBinaryType::NONE) |
||
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; |
||
132 | virtual ~LVReader() { |
||
133 | if (Root) |
||
134 | delete Root; |
||
135 | } |
||
136 | |||
137 | StringRef getFilename(LVObject *Object, size_t Index) const; |
||
138 | StringRef getFilename() const { return InputFilename; } |
||
139 | void setFilename(std::string Name) { InputFilename = std::move(Name); } |
||
140 | StringRef getFileFormatName() const { return FileFormatName; } |
||
141 | |||
142 | raw_ostream &outputStream() { return OS; } |
||
143 | |||
144 | bool isBinaryTypeNone() const { return BinaryType == LVBinaryType::NONE; } |
||
145 | bool isBinaryTypeELF() const { return BinaryType == LVBinaryType::ELF; } |
||
146 | bool isBinaryTypeCOFF() const { return BinaryType == LVBinaryType::COFF; } |
||
147 | |||
148 | LVScopeCompileUnit *getCompileUnit() const { return CompileUnit; } |
||
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. |
||
155 | LVScopeRoot *getScopesRoot() const { return Root; } |
||
156 | |||
157 | Error doPrint(); |
||
158 | Error doLoad(); |
||
159 | |||
160 | virtual std::string getRegisterName(LVSmall Opcode, uint64_t Operands[2]) { |
||
161 | llvm_unreachable("Invalid instance reader."); |
||
162 | return {}; |
||
163 | } |
||
164 | |||
165 | LVSectionIndex getDotTextSectionIndex() const { return DotTextSectionIndex; } |
||
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. |
||
175 | LVSplitContext &getSplitContext() { return SplitContext; } |
||
176 | |||
177 | // In the case of element comparison, register that added element. |
||
178 | void notifyAddedElement(LVLine *Line) { |
||
179 | if (!options().getCompareContext() && options().getCompareLines()) |
||
180 | Lines.push_back(Line); |
||
181 | } |
||
182 | void notifyAddedElement(LVScope *Scope) { |
||
183 | if (!options().getCompareContext() && options().getCompareScopes()) |
||
184 | Scopes.push_back(Scope); |
||
185 | } |
||
186 | void notifyAddedElement(LVSymbol *Symbol) { |
||
187 | if (!options().getCompareContext() && options().getCompareSymbols()) |
||
188 | Symbols.push_back(Symbol); |
||
189 | } |
||
190 | void notifyAddedElement(LVType *Type) { |
||
191 | if (!options().getCompareContext() && options().getCompareTypes()) |
||
192 | Types.push_back(Type); |
||
193 | } |
||
194 | |||
195 | const LVLines &getLines() const { return Lines; } |
||
196 | const LVScopes &getScopes() const { return Scopes; } |
||
197 | const LVSymbols &getSymbols() const { return Symbols; } |
||
198 | const LVTypes &getTypes() const { return Types; } |
||
199 | |||
200 | // Conditions to print an object. |
||
201 | bool doPrintLine(const LVLine *Line) const { |
||
202 | return patterns().printElement(Line); |
||
203 | } |
||
204 | bool doPrintLocation(const LVLocation *Location) const { |
||
205 | return patterns().printObject(Location); |
||
206 | } |
||
207 | bool doPrintScope(const LVScope *Scope) const { |
||
208 | return patterns().printElement(Scope); |
||
209 | } |
||
210 | bool doPrintSymbol(const LVSymbol *Symbol) const { |
||
211 | return patterns().printElement(Symbol); |
||
212 | } |
||
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; |
||
221 | virtual void printRecords(raw_ostream &OS) const {} |
||
222 | |||
223 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
||
224 | void dump() const { print(dbgs()); } |
||
225 | #endif |
||
226 | }; |
||
227 | |||
228 | inline LVReader &getReader() { return LVReader::getInstance(); } |
||
229 | inline LVSplitContext &getReaderSplitContext() { |
||
230 | return getReader().getSplitContext(); |
||
231 | } |
||
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 |