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