#pragma once #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif //===-- LVReader.h ----------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the LVReader class, which is used to describe a debug // information reader. // //===----------------------------------------------------------------------===// #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVREADER_H #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVREADER_H #include "llvm/DebugInfo/LogicalView/Core/LVOptions.h" #include "llvm/DebugInfo/LogicalView/Core/LVRange.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/ToolOutputFile.h" #include <map> namespace llvm { namespace logicalview { constexpr LVSectionIndex UndefinedSectionIndex = 0; class LVScopeCompileUnit; class LVObject; class LVSplitContext final { std::unique_ptr<ToolOutputFile> OutputFile; std::string Location; public: LVSplitContext() = default; LVSplitContext(const LVSplitContext &) = delete; LVSplitContext &operator=(const LVSplitContext &) = delete; ~LVSplitContext() = default; Error createSplitFolder(StringRef Where); std::error_code open(std::string Name, std::string Extension, raw_ostream &OS); void close() { if (OutputFile) { OutputFile->os().close(); OutputFile = nullptr; } } std::string getLocation() const { return Location; } raw_fd_ostream &os() { return OutputFile->os(); } }; class LVReader { LVBinaryType BinaryType; // Context used by '--output=split' command line option. LVSplitContext SplitContext; // Compile Units DIE Offset => Scope. using LVCompileUnits = std::map<LVOffset, LVScopeCompileUnit *>; LVCompileUnits CompileUnits; // Added elements to be used during elements comparison. LVLines Lines; LVScopes Scopes; LVSymbols Symbols; LVTypes Types; // Create split folder. Error createSplitFolder(); bool OutputSplit = false; protected: LVScopeRoot *Root = nullptr; std::string InputFilename; std::string FileFormatName; ScopedPrinter &W; raw_ostream &OS; LVScopeCompileUnit *CompileUnit = nullptr; // Only for ELF format. The CodeView is handled in a different way. LVSectionIndex DotTextSectionIndex = UndefinedSectionIndex; // Record Compilation Unit entry. void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) { CompileUnits.emplace(Offset, CompileUnit); } // Create the Scope Root. virtual Error createScopes() { Root = new LVScopeRoot(); Root->setName(getFilename()); if (options().getAttributeFormat()) Root->setFileFormatName(FileFormatName); return Error::success(); } // Return a pathname composed by: parent_path(InputFilename)/filename(From). // This is useful when a type server (PDB file associated with an object // file or a precompiled header file) or a DWARF split object have been // moved from their original location. That is the case when running // regression tests, where object files are created in one location and // executed in a different location. std::string createAlternativePath(StringRef From) { // During the reader initialization, any backslashes in 'InputFilename' // are converted to forward slashes. SmallString<128> Path; sys::path::append(Path, sys::path::Style::posix, sys::path::parent_path(InputFilename), sys::path::filename(sys::path::convert_to_slash( From, sys::path::Style::windows))); return std::string(Path); } virtual Error printScopes(); virtual Error printMatchedElements(bool UseMatchedElements); virtual void sortScopes() {} public: LVReader() = delete; LVReader(StringRef InputFilename, StringRef FileFormatName, ScopedPrinter &W, LVBinaryType BinaryType = LVBinaryType::NONE) : BinaryType(BinaryType), OutputSplit(options().getOutputSplit()), InputFilename(InputFilename), FileFormatName(FileFormatName), W(W), OS(W.getOStream()) {} LVReader(const LVReader &) = delete; LVReader &operator=(const LVReader &) = delete; virtual ~LVReader() { if (Root) delete Root; } StringRef getFilename(LVObject *Object, size_t Index) const; StringRef getFilename() const { return InputFilename; } void setFilename(std::string Name) { InputFilename = std::move(Name); } StringRef getFileFormatName() const { return FileFormatName; } raw_ostream &outputStream() { return OS; } bool isBinaryTypeNone() const { return BinaryType == LVBinaryType::NONE; } bool isBinaryTypeELF() const { return BinaryType == LVBinaryType::ELF; } bool isBinaryTypeCOFF() const { return BinaryType == LVBinaryType::COFF; } LVScopeCompileUnit *getCompileUnit() const { return CompileUnit; } void setCompileUnit(LVScope *Scope) { assert(Scope && Scope->isCompileUnit() && "Scope is not a compile unit"); CompileUnit = static_cast<LVScopeCompileUnit *>(Scope); } // Access to the scopes root. LVScopeRoot *getScopesRoot() const { return Root; } Error doPrint(); Error doLoad(); virtual std::string getRegisterName(LVSmall Opcode, uint64_t Operands[2]) { llvm_unreachable("Invalid instance reader."); return {}; } LVSectionIndex getDotTextSectionIndex() const { return DotTextSectionIndex; } virtual LVSectionIndex getSectionIndex(LVScope *Scope) { return getDotTextSectionIndex(); } virtual bool isSystemEntry(LVElement *Element, StringRef Name = {}) const { return false; }; // Access to split context. LVSplitContext &getSplitContext() { return SplitContext; } // In the case of element comparison, register that added element. void notifyAddedElement(LVLine *Line) { if (!options().getCompareContext() && options().getCompareLines()) Lines.push_back(Line); } void notifyAddedElement(LVScope *Scope) { if (!options().getCompareContext() && options().getCompareScopes()) Scopes.push_back(Scope); } void notifyAddedElement(LVSymbol *Symbol) { if (!options().getCompareContext() && options().getCompareSymbols()) Symbols.push_back(Symbol); } void notifyAddedElement(LVType *Type) { if (!options().getCompareContext() && options().getCompareTypes()) Types.push_back(Type); } const LVLines &getLines() const { return Lines; } const LVScopes &getScopes() const { return Scopes; } const LVSymbols &getSymbols() const { return Symbols; } const LVTypes &getTypes() const { return Types; } // Conditions to print an object. bool doPrintLine(const LVLine *Line) const { return patterns().printElement(Line); } bool doPrintLocation(const LVLocation *Location) const { return patterns().printObject(Location); } bool doPrintScope(const LVScope *Scope) const { return patterns().printElement(Scope); } bool doPrintSymbol(const LVSymbol *Symbol) const { return patterns().printElement(Symbol); } bool doPrintType(const LVType *Type) const { return patterns().printElement(Type); } static LVReader &getInstance(); static void setInstance(LVReader *Reader); void print(raw_ostream &OS) const; virtual void printRecords(raw_ostream &OS) const {} #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() const { print(dbgs()); } #endif }; inline LVReader &getReader() { return LVReader::getInstance(); } inline LVSplitContext &getReaderSplitContext() { return getReader().getSplitContext(); } inline LVScopeCompileUnit *getReaderCompileUnit() { return getReader().getCompileUnit(); } } // end namespace logicalview } // end namespace llvm #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVREADER_H #ifdef __GNUC__ #pragma GCC diagnostic pop #endif