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