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