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
27namespace lldb_private {
28class RegularExpression;
29class Stream;
30class SymbolContextList;
31class Target;
32
33class SourceManager {
34public:
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 &regex, 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
59 const FileSpec &GetFileSpec() { return m_file_spec; }
60
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
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.
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
142 FileSP GetLastFile() { return GetFile(file_spec: 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
164 bool DefaultFileAndLineSet() {
165 return (GetFile(file_spec: m_last_file_spec).get() != nullptr);
166 }
167
168 void FindLinesMatchingRegex(FileSpec &file_spec, RegularExpression &regex,
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
174protected:
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
182private:
183 SourceManager(const SourceManager &) = delete;
184 const SourceManager &operator=(const SourceManager &) = delete;
185};
186
187bool operator==(const SourceManager::File &lhs, const SourceManager::File &rhs);
188
189} // namespace lldb_private
190
191#endif // LLDB_CORE_SOURCEMANAGER_H
192

source code of lldb/include/lldb/Core/SourceManager.h