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 /// The logical reader owns of all the logical elements created during
58 /// the debug information parsing. For its creation it uses a specific
59 /// bump allocator for each type of logical element.
60 class LVReader {
61 LVBinaryType BinaryType;
62
63 // Context used by '--output=split' command line option.
64 LVSplitContext SplitContext;
65
66 // Compile Units DIE Offset => Scope.
67 using LVCompileUnits = std::map<LVOffset, LVScopeCompileUnit *>;
68 LVCompileUnits CompileUnits;
69
70 // Added elements to be used during elements comparison.
71 LVLines Lines;
72 LVScopes Scopes;
73 LVSymbols Symbols;
74 LVTypes Types;
75
76 // Create split folder.
77 Error createSplitFolder();
78 bool OutputSplit = false;
79
80 // Define a specific bump allocator for the given KIND.
81 #define LV_OBJECT_ALLOCATOR(KIND) \
82 llvm::SpecificBumpPtrAllocator<LV##KIND> Allocated##KIND;
83
84 // Lines allocator.
85 LV_OBJECT_ALLOCATOR(Line)
86 LV_OBJECT_ALLOCATOR(LineDebug)
87 LV_OBJECT_ALLOCATOR(LineAssembler)
88
89 // Locations allocator.
90 LV_OBJECT_ALLOCATOR(Location)
91 LV_OBJECT_ALLOCATOR(LocationSymbol)
92
93 // Operations allocator.
94 LV_OBJECT_ALLOCATOR(Operation)
95
96 // Scopes allocator.
97 LV_OBJECT_ALLOCATOR(Scope)
98 LV_OBJECT_ALLOCATOR(ScopeAggregate)
99 LV_OBJECT_ALLOCATOR(ScopeAlias)
100 LV_OBJECT_ALLOCATOR(ScopeArray)
101 LV_OBJECT_ALLOCATOR(ScopeCompileUnit)
102 LV_OBJECT_ALLOCATOR(ScopeEnumeration)
103 LV_OBJECT_ALLOCATOR(ScopeFormalPack)
104 LV_OBJECT_ALLOCATOR(ScopeFunction)
105 LV_OBJECT_ALLOCATOR(ScopeFunctionInlined)
106 LV_OBJECT_ALLOCATOR(ScopeFunctionType)
107 LV_OBJECT_ALLOCATOR(ScopeNamespace)
108 LV_OBJECT_ALLOCATOR(ScopeRoot)
109 LV_OBJECT_ALLOCATOR(ScopeTemplatePack)
110
111 // Symbols allocator.
112 LV_OBJECT_ALLOCATOR(Symbol)
113
114 // Types allocator.
115 LV_OBJECT_ALLOCATOR(Type)
116 LV_OBJECT_ALLOCATOR(TypeDefinition)
117 LV_OBJECT_ALLOCATOR(TypeEnumerator)
118 LV_OBJECT_ALLOCATOR(TypeImport)
119 LV_OBJECT_ALLOCATOR(TypeParam)
120 LV_OBJECT_ALLOCATOR(TypeSubrange)
121
122 #undef LV_OBJECT_ALLOCATOR
123
124 protected:
125 LVScopeRoot *Root = nullptr;
126 std::string InputFilename;
127 std::string FileFormatName;
128 ScopedPrinter &W;
129 raw_ostream &OS;
130 LVScopeCompileUnit *CompileUnit = nullptr;
131
132 // Only for ELF format. The CodeView is handled in a different way.
133 LVSectionIndex DotTextSectionIndex = UndefinedSectionIndex;
134
135 // Record Compilation Unit entry.
addCompileUnitOffset(LVOffset Offset,LVScopeCompileUnit * CompileUnit)136 void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) {
137 CompileUnits.emplace(Offset, CompileUnit);
138 }
139
140 // Create the Scope Root.
createScopes()141 virtual Error createScopes() {
142 Root = createScopeRoot();
143 Root->setName(getFilename());
144 if (options().getAttributeFormat())
145 Root->setFileFormatName(FileFormatName);
146 return Error::success();
147 }
148
149 // Return a pathname composed by: parent_path(InputFilename)/filename(From).
150 // This is useful when a type server (PDB file associated with an object
151 // file or a precompiled header file) or a DWARF split object have been
152 // moved from their original location. That is the case when running
153 // regression tests, where object files are created in one location and
154 // executed in a different location.
createAlternativePath(StringRef From)155 std::string createAlternativePath(StringRef From) {
156 // During the reader initialization, any backslashes in 'InputFilename'
157 // are converted to forward slashes.
158 SmallString<128> Path;
159 sys::path::append(Path, sys::path::Style::posix,
160 sys::path::parent_path(InputFilename),
161 sys::path::filename(sys::path::convert_to_slash(
162 From, sys::path::Style::windows)));
163 return std::string(Path);
164 }
165
166 virtual Error printScopes();
167 virtual Error printMatchedElements(bool UseMatchedElements);
sortScopes()168 virtual void sortScopes() {}
169
170 public:
171 LVReader() = delete;
172 LVReader(StringRef InputFilename, StringRef FileFormatName, ScopedPrinter &W,
173 LVBinaryType BinaryType = LVBinaryType::NONE)
BinaryType(BinaryType)174 : BinaryType(BinaryType), OutputSplit(options().getOutputSplit()),
175 InputFilename(InputFilename), FileFormatName(FileFormatName), W(W),
176 OS(W.getOStream()) {}
177 LVReader(const LVReader &) = delete;
178 LVReader &operator=(const LVReader &) = delete;
179 virtual ~LVReader() = default;
180
181 // Creates a logical object of the given KIND. The signature for the created
182 // functions looks like:
183 // ...
184 // LVScope *createScope()
185 // LVScopeRoot *creatScopeRoot()
186 // LVType *createType();
187 // ...
188 #define LV_CREATE_OBJECT(KIND) \
189 LV##KIND *create##KIND() { \
190 return new (Allocated##KIND.Allocate()) LV##KIND(); \
191 }
192
193 // Lines creation.
194 LV_CREATE_OBJECT(Line)
LV_CREATE_OBJECT(LineDebug)195 LV_CREATE_OBJECT(LineDebug)
196 LV_CREATE_OBJECT(LineAssembler)
197
198 // Locations creation.
199 LV_CREATE_OBJECT(Location)
200 LV_CREATE_OBJECT(LocationSymbol)
201
202 // Scopes creation.
203 LV_CREATE_OBJECT(Scope)
204 LV_CREATE_OBJECT(ScopeAggregate)
205 LV_CREATE_OBJECT(ScopeAlias)
206 LV_CREATE_OBJECT(ScopeArray)
207 LV_CREATE_OBJECT(ScopeCompileUnit)
208 LV_CREATE_OBJECT(ScopeEnumeration)
209 LV_CREATE_OBJECT(ScopeFormalPack)
210 LV_CREATE_OBJECT(ScopeFunction)
211 LV_CREATE_OBJECT(ScopeFunctionInlined)
212 LV_CREATE_OBJECT(ScopeFunctionType)
213 LV_CREATE_OBJECT(ScopeNamespace)
214 LV_CREATE_OBJECT(ScopeRoot)
215 LV_CREATE_OBJECT(ScopeTemplatePack)
216
217 // Symbols creation.
218 LV_CREATE_OBJECT(Symbol)
219
220 // Types creation.
221 LV_CREATE_OBJECT(Type)
222 LV_CREATE_OBJECT(TypeDefinition)
223 LV_CREATE_OBJECT(TypeEnumerator)
224 LV_CREATE_OBJECT(TypeImport)
225 LV_CREATE_OBJECT(TypeParam)
226 LV_CREATE_OBJECT(TypeSubrange)
227
228 #undef LV_CREATE_OBJECT
229
230 // Operations creation.
231 LVOperation *createOperation(LVSmall OpCode, ArrayRef<LVUnsigned> Operands) {
232 return new (AllocatedOperation.Allocate()) LVOperation(OpCode, Operands);
233 }
234
235 StringRef getFilename(LVObject *Object, size_t Index) const;
getFilename()236 StringRef getFilename() const { return InputFilename; }
setFilename(std::string Name)237 void setFilename(std::string Name) { InputFilename = std::move(Name); }
getFileFormatName()238 StringRef getFileFormatName() const { return FileFormatName; }
239
outputStream()240 raw_ostream &outputStream() { return OS; }
241
isBinaryTypeNone()242 bool isBinaryTypeNone() const { return BinaryType == LVBinaryType::NONE; }
isBinaryTypeELF()243 bool isBinaryTypeELF() const { return BinaryType == LVBinaryType::ELF; }
isBinaryTypeCOFF()244 bool isBinaryTypeCOFF() const { return BinaryType == LVBinaryType::COFF; }
245
getCompileUnit()246 LVScopeCompileUnit *getCompileUnit() const { return CompileUnit; }
setCompileUnit(LVScope * Scope)247 void setCompileUnit(LVScope *Scope) {
248 assert(Scope && Scope->isCompileUnit() && "Scope is not a compile unit");
249 CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
250 }
setCompileUnitCPUType(codeview::CPUType Type)251 void setCompileUnitCPUType(codeview::CPUType Type) {
252 CompileUnit->setCPUType(Type);
253 }
getCompileUnitCPUType()254 codeview::CPUType getCompileUnitCPUType() {
255 return CompileUnit->getCPUType();
256 }
257
258 // Access to the scopes root.
getScopesRoot()259 LVScopeRoot *getScopesRoot() const { return Root; }
260
261 Error doPrint();
262 Error doLoad();
263
getRegisterName(LVSmall Opcode,ArrayRef<uint64_t> Operands)264 virtual std::string getRegisterName(LVSmall Opcode,
265 ArrayRef<uint64_t> Operands) {
266 llvm_unreachable("Invalid instance reader.");
267 return {};
268 }
269
getDotTextSectionIndex()270 LVSectionIndex getDotTextSectionIndex() const { return DotTextSectionIndex; }
getSectionIndex(LVScope * Scope)271 virtual LVSectionIndex getSectionIndex(LVScope *Scope) {
272 return getDotTextSectionIndex();
273 }
274
275 virtual bool isSystemEntry(LVElement *Element, StringRef Name = {}) const {
276 return false;
277 };
278
279 // Access to split context.
getSplitContext()280 LVSplitContext &getSplitContext() { return SplitContext; }
281
282 // In the case of element comparison, register that added element.
notifyAddedElement(LVLine * Line)283 void notifyAddedElement(LVLine *Line) {
284 if (!options().getCompareContext() && options().getCompareLines())
285 Lines.push_back(Line);
286 }
notifyAddedElement(LVScope * Scope)287 void notifyAddedElement(LVScope *Scope) {
288 if (!options().getCompareContext() && options().getCompareScopes())
289 Scopes.push_back(Scope);
290 }
notifyAddedElement(LVSymbol * Symbol)291 void notifyAddedElement(LVSymbol *Symbol) {
292 if (!options().getCompareContext() && options().getCompareSymbols())
293 Symbols.push_back(Symbol);
294 }
notifyAddedElement(LVType * Type)295 void notifyAddedElement(LVType *Type) {
296 if (!options().getCompareContext() && options().getCompareTypes())
297 Types.push_back(Type);
298 }
299
getLines()300 const LVLines &getLines() const { return Lines; }
getScopes()301 const LVScopes &getScopes() const { return Scopes; }
getSymbols()302 const LVSymbols &getSymbols() const { return Symbols; }
getTypes()303 const LVTypes &getTypes() const { return Types; }
304
305 // Conditions to print an object.
doPrintLine(const LVLine * Line)306 bool doPrintLine(const LVLine *Line) const {
307 return patterns().printElement(Line);
308 }
doPrintLocation(const LVLocation * Location)309 bool doPrintLocation(const LVLocation *Location) const {
310 return patterns().printObject(Location);
311 }
doPrintScope(const LVScope * Scope)312 bool doPrintScope(const LVScope *Scope) const {
313 return patterns().printElement(Scope);
314 }
doPrintSymbol(const LVSymbol * Symbol)315 bool doPrintSymbol(const LVSymbol *Symbol) const {
316 return patterns().printElement(Symbol);
317 }
doPrintType(const LVType * Type)318 bool doPrintType(const LVType *Type) const {
319 return patterns().printElement(Type);
320 }
321
322 static LVReader &getInstance();
323 static void setInstance(LVReader *Reader);
324
325 void print(raw_ostream &OS) const;
printRecords(raw_ostream & OS)326 virtual void printRecords(raw_ostream &OS) const {}
327
328 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()329 void dump() const { print(dbgs()); }
330 #endif
331 };
332
getReader()333 inline LVReader &getReader() { return LVReader::getInstance(); }
getReaderSplitContext()334 inline LVSplitContext &getReaderSplitContext() {
335 return getReader().getSplitContext();
336 }
getReaderCompileUnit()337 inline LVScopeCompileUnit *getReaderCompileUnit() {
338 return getReader().getCompileUnit();
339 }
340
341 } // end namespace logicalview
342 } // end namespace llvm
343
344 #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVREADER_H
345