xref: /openbsd-src/gnu/llvm/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
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