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 /// 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. 136 void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) { 137 CompileUnits.emplace(Offset, CompileUnit); 138 } 139 140 // Create the Scope Root. 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. 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); 168 virtual void sortScopes() {} 169 170 public: 171 LVReader() = delete; 172 LVReader(StringRef InputFilename, StringRef FileFormatName, ScopedPrinter &W, 173 LVBinaryType BinaryType = LVBinaryType::NONE) 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) 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; 236 StringRef getFilename() const { return InputFilename; } 237 void setFilename(std::string Name) { InputFilename = std::move(Name); } 238 StringRef getFileFormatName() const { return FileFormatName; } 239 240 raw_ostream &outputStream() { return OS; } 241 242 bool isBinaryTypeNone() const { return BinaryType == LVBinaryType::NONE; } 243 bool isBinaryTypeELF() const { return BinaryType == LVBinaryType::ELF; } 244 bool isBinaryTypeCOFF() const { return BinaryType == LVBinaryType::COFF; } 245 246 LVScopeCompileUnit *getCompileUnit() const { return CompileUnit; } 247 void setCompileUnit(LVScope *Scope) { 248 assert(Scope && Scope->isCompileUnit() && "Scope is not a compile unit"); 249 CompileUnit = static_cast<LVScopeCompileUnit *>(Scope); 250 } 251 void setCompileUnitCPUType(codeview::CPUType Type) { 252 CompileUnit->setCPUType(Type); 253 } 254 codeview::CPUType getCompileUnitCPUType() { 255 return CompileUnit->getCPUType(); 256 } 257 258 // Access to the scopes root. 259 LVScopeRoot *getScopesRoot() const { return Root; } 260 261 Error doPrint(); 262 Error doLoad(); 263 264 virtual std::string getRegisterName(LVSmall Opcode, 265 ArrayRef<uint64_t> Operands) { 266 llvm_unreachable("Invalid instance reader."); 267 return {}; 268 } 269 270 LVSectionIndex getDotTextSectionIndex() const { return DotTextSectionIndex; } 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. 280 LVSplitContext &getSplitContext() { return SplitContext; } 281 282 // In the case of element comparison, register that added element. 283 void notifyAddedElement(LVLine *Line) { 284 if (!options().getCompareContext() && options().getCompareLines()) 285 Lines.push_back(Line); 286 } 287 void notifyAddedElement(LVScope *Scope) { 288 if (!options().getCompareContext() && options().getCompareScopes()) 289 Scopes.push_back(Scope); 290 } 291 void notifyAddedElement(LVSymbol *Symbol) { 292 if (!options().getCompareContext() && options().getCompareSymbols()) 293 Symbols.push_back(Symbol); 294 } 295 void notifyAddedElement(LVType *Type) { 296 if (!options().getCompareContext() && options().getCompareTypes()) 297 Types.push_back(Type); 298 } 299 300 const LVLines &getLines() const { return Lines; } 301 const LVScopes &getScopes() const { return Scopes; } 302 const LVSymbols &getSymbols() const { return Symbols; } 303 const LVTypes &getTypes() const { return Types; } 304 305 // Conditions to print an object. 306 bool doPrintLine(const LVLine *Line) const { 307 return patterns().printElement(Line); 308 } 309 bool doPrintLocation(const LVLocation *Location) const { 310 return patterns().printObject(Location); 311 } 312 bool doPrintScope(const LVScope *Scope) const { 313 return patterns().printElement(Scope); 314 } 315 bool doPrintSymbol(const LVSymbol *Symbol) const { 316 return patterns().printElement(Symbol); 317 } 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; 326 virtual void printRecords(raw_ostream &OS) const {} 327 328 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 329 void dump() const { print(dbgs()); } 330 #endif 331 }; 332 333 inline LVReader &getReader() { return LVReader::getInstance(); } 334 inline LVSplitContext &getReaderSplitContext() { 335 return getReader().getSplitContext(); 336 } 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