1 //===-- SourceManager.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 #ifndef LLDB_CORE_SOURCEMANAGER_H 10 #define LLDB_CORE_SOURCEMANAGER_H 11 12 #include "lldb/Utility/FileSpec.h" 13 #include "lldb/lldb-defines.h" 14 #include "lldb/lldb-forward.h" 15 16 #include "llvm/Support/Chrono.h" 17 18 #include <cstddef> 19 #include <cstdint> 20 #include <map> 21 #include <memory> 22 #include <optional> 23 #include <string> 24 #include <vector> 25 26 namespace lldb_private { 27 class RegularExpression; 28 class Stream; 29 class SymbolContextList; 30 class Target; 31 32 class SourceManager { 33 public: 34 class File { 35 friend bool operator==(const SourceManager::File &lhs, 36 const SourceManager::File &rhs); 37 38 public: 39 File(const FileSpec &file_spec, Target *target); 40 File(const FileSpec &file_spec, lldb::DebuggerSP debugger_sp); 41 ~File() = default; 42 43 void UpdateIfNeeded(); 44 45 size_t DisplaySourceLines(uint32_t line, std::optional<size_t> column, 46 uint32_t context_before, uint32_t context_after, 47 Stream *s); 48 void FindLinesMatchingRegex(RegularExpression ®ex, uint32_t start_line, 49 uint32_t end_line, 50 std::vector<uint32_t> &match_lines); 51 52 bool GetLine(uint32_t line_no, std::string &buffer); 53 54 uint32_t GetLineOffset(uint32_t line); 55 56 bool LineIsValid(uint32_t line); 57 GetFileSpec()58 const FileSpec &GetFileSpec() { return m_file_spec; } 59 GetSourceMapModificationID()60 uint32_t GetSourceMapModificationID() const { return m_source_map_mod_id; } 61 62 const char *PeekLineData(uint32_t line); 63 64 uint32_t GetLineLength(uint32_t line, bool include_newline_chars); 65 66 uint32_t GetNumLines(); 67 68 protected: 69 bool CalculateLineOffsets(uint32_t line = UINT32_MAX); 70 71 FileSpec m_file_spec_orig; // The original file spec that was used (can be 72 // different from m_file_spec) 73 FileSpec m_file_spec; // The actually file spec being used (if the target 74 // has source mappings, this might be different from 75 // m_file_spec_orig) 76 77 // Keep the modification time that this file data is valid for 78 llvm::sys::TimePoint<> m_mod_time; 79 80 // If the target uses path remappings, be sure to clear our notion of a 81 // source file if the path modification ID changes 82 uint32_t m_source_map_mod_id = 0; 83 lldb::DataBufferSP m_data_sp; 84 typedef std::vector<uint32_t> LineOffsets; 85 LineOffsets m_offsets; 86 lldb::DebuggerWP m_debugger_wp; 87 88 private: 89 void CommonInitializer(const FileSpec &file_spec, Target *target); 90 }; 91 92 typedef std::shared_ptr<File> FileSP; 93 94 // The SourceFileCache class separates the source manager from the cache of 95 // source files, so the cache can be stored in the Debugger, but the source 96 // managers can be per target. 97 class SourceFileCache { 98 public: 99 SourceFileCache() = default; 100 ~SourceFileCache() = default; 101 102 void AddSourceFile(const FileSP &file_sp); 103 FileSP FindSourceFile(const FileSpec &file_spec) const; 104 105 // Removes all elements from the cache. Clear()106 void Clear() { m_file_cache.clear(); } 107 108 protected: 109 typedef std::map<FileSpec, FileSP> FileCache; 110 FileCache m_file_cache; 111 }; 112 113 // Constructors and Destructors 114 // A source manager can be made with a non-null target, in which case it can 115 // use the path remappings to find 116 // source files that are not in their build locations. With no target it 117 // won't be able to do this. 118 SourceManager(const lldb::DebuggerSP &debugger_sp); 119 SourceManager(const lldb::TargetSP &target_sp); 120 121 ~SourceManager(); 122 GetLastFile()123 FileSP GetLastFile() { return GetFile(m_last_file_spec); } 124 125 size_t 126 DisplaySourceLinesWithLineNumbers(const FileSpec &file, uint32_t line, 127 uint32_t column, uint32_t context_before, 128 uint32_t context_after, 129 const char *current_line_cstr, Stream *s, 130 const SymbolContextList *bp_locs = nullptr); 131 132 // This variant uses the last file we visited. 133 size_t DisplaySourceLinesWithLineNumbersUsingLastFile( 134 uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column, 135 const char *current_line_cstr, Stream *s, 136 const SymbolContextList *bp_locs = nullptr); 137 138 size_t DisplayMoreWithLineNumbers(Stream *s, uint32_t count, bool reverse, 139 const SymbolContextList *bp_locs = nullptr); 140 141 bool SetDefaultFileAndLine(const FileSpec &file_spec, uint32_t line); 142 143 bool GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line); 144 DefaultFileAndLineSet()145 bool DefaultFileAndLineSet() { 146 return (GetFile(m_last_file_spec).get() != nullptr); 147 } 148 149 void FindLinesMatchingRegex(FileSpec &file_spec, RegularExpression ®ex, 150 uint32_t start_line, uint32_t end_line, 151 std::vector<uint32_t> &match_lines); 152 153 FileSP GetFile(const FileSpec &file_spec); 154 155 protected: 156 FileSpec m_last_file_spec; 157 uint32_t m_last_line; 158 uint32_t m_last_count; 159 bool m_default_set; 160 lldb::TargetWP m_target_wp; 161 lldb::DebuggerWP m_debugger_wp; 162 163 private: 164 SourceManager(const SourceManager &) = delete; 165 const SourceManager &operator=(const SourceManager &) = delete; 166 }; 167 168 bool operator==(const SourceManager::File &lhs, const SourceManager::File &rhs); 169 170 } // namespace lldb_private 171 172 #endif // LLDB_CORE_SOURCEMANAGER_H 173