[libc] Switch to using the generic `<gpuintrin.h>` implementations (#121810)
[llvm-project.git] / lldb / source / Target / PathMappingList.cpp
blob16456d110a9336da425e12434089bb04fd1c734f
1 //===-- PathMappingList.cpp -----------------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include <climits>
10 #include <cstring>
11 #include <optional>
13 #include "lldb/Host/FileSystem.h"
14 #include "lldb/Host/PosixApi.h"
15 #include "lldb/Target/PathMappingList.h"
16 #include "lldb/Utility/FileSpec.h"
17 #include "lldb/Utility/Status.h"
18 #include "lldb/Utility/Stream.h"
19 #include "lldb/lldb-private-enumerations.h"
21 using namespace lldb;
22 using namespace lldb_private;
24 namespace {
25 // We must normalize our path pairs that we store because if we don't then
26 // things won't always work. We found a case where if we did:
27 // (lldb) settings set target.source-map . /tmp
28 // We would store a path pairs of "." and "/tmp" as raw strings. If the debug
29 // info contains "./foo/bar.c", the path will get normalized to "foo/bar.c".
30 // When PathMappingList::RemapPath() is called, it expects the path to start
31 // with the raw path pair, which doesn't work anymore because the paths have
32 // been normalized when the debug info was loaded. So we need to store
33 // nomalized path pairs to ensure things match up.
34 std::string NormalizePath(llvm::StringRef path) {
35 // If we use "path" to construct a FileSpec, it will normalize the path for
36 // us. We then grab the string.
37 return FileSpec(path).GetPath();
40 // PathMappingList constructor
41 PathMappingList::PathMappingList() : m_pairs() {}
43 PathMappingList::PathMappingList(ChangedCallback callback, void *callback_baton)
44 : m_pairs(), m_callback(callback), m_callback_baton(callback_baton) {}
46 PathMappingList::PathMappingList(const PathMappingList &rhs)
47 : m_pairs(rhs.m_pairs) {}
49 const PathMappingList &PathMappingList::operator=(const PathMappingList &rhs) {
50 if (this != &rhs) {
51 std::scoped_lock<std::mutex, std::mutex, std::mutex> locks(
52 m_callback_mutex, m_pairs_mutex, rhs.m_pairs_mutex);
53 m_pairs = rhs.m_pairs;
54 m_callback = nullptr;
55 m_callback_baton = nullptr;
56 m_mod_id = rhs.m_mod_id;
58 return *this;
61 PathMappingList::~PathMappingList() = default;
63 void PathMappingList::AppendNoLock(llvm::StringRef path,
64 llvm::StringRef replacement) {
65 ++m_mod_id;
66 m_pairs.emplace_back(pair(NormalizePath(path), NormalizePath(replacement)));
69 void PathMappingList::Notify(bool notify) const {
70 ChangedCallback callback = nullptr;
71 void *baton = nullptr;
73 std::lock_guard<std::mutex> lock(m_callback_mutex);
74 callback = m_callback;
75 baton = m_callback_baton;
77 if (notify && callback)
78 callback(*this, baton);
81 void PathMappingList::Append(llvm::StringRef path, llvm::StringRef replacement,
82 bool notify) {
84 std::lock_guard<std::mutex> lock(m_pairs_mutex);
85 AppendNoLock(path, replacement);
87 Notify(notify);
90 void PathMappingList::Append(const PathMappingList &rhs, bool notify) {
92 std::scoped_lock<std::mutex, std::mutex> locks(m_pairs_mutex,
93 rhs.m_pairs_mutex);
94 ++m_mod_id;
95 if (rhs.m_pairs.empty())
96 return;
97 const_iterator pos, end = rhs.m_pairs.end();
98 for (pos = rhs.m_pairs.begin(); pos != end; ++pos)
99 m_pairs.push_back(*pos);
101 Notify(notify);
104 bool PathMappingList::AppendUnique(llvm::StringRef path,
105 llvm::StringRef replacement, bool notify) {
106 auto normalized_path = NormalizePath(path);
107 auto normalized_replacement = NormalizePath(replacement);
109 std::lock_guard<std::mutex> lock(m_pairs_mutex);
110 for (const auto &pair : m_pairs) {
111 if (pair.first.GetStringRef() == normalized_path &&
112 pair.second.GetStringRef() == normalized_replacement)
113 return false;
115 AppendNoLock(path, replacement);
117 Notify(notify);
118 return true;
121 void PathMappingList::Insert(llvm::StringRef path, llvm::StringRef replacement,
122 uint32_t index, bool notify) {
124 std::lock_guard<std::mutex> lock(m_pairs_mutex);
125 ++m_mod_id;
126 iterator insert_iter;
127 if (index >= m_pairs.size())
128 insert_iter = m_pairs.end();
129 else
130 insert_iter = m_pairs.begin() + index;
131 m_pairs.emplace(insert_iter,
132 pair(NormalizePath(path), NormalizePath(replacement)));
134 Notify(notify);
137 bool PathMappingList::Replace(llvm::StringRef path, llvm::StringRef replacement,
138 uint32_t index, bool notify) {
140 std::lock_guard<std::mutex> lock(m_pairs_mutex);
141 if (index >= m_pairs.size())
142 return false;
143 ++m_mod_id;
144 m_pairs[index] = pair(NormalizePath(path), NormalizePath(replacement));
146 Notify(notify);
147 return true;
150 bool PathMappingList::Remove(size_t index, bool notify) {
152 std::lock_guard<std::mutex> lock(m_pairs_mutex);
153 if (index >= m_pairs.size())
154 return false;
156 ++m_mod_id;
157 iterator iter = m_pairs.begin() + index;
158 m_pairs.erase(iter);
160 Notify(notify);
161 return true;
164 // For clients which do not need the pair index dumped, pass a pair_index >= 0
165 // to only dump the indicated pair.
166 void PathMappingList::Dump(Stream *s, int pair_index) {
167 std::lock_guard<std::mutex> lock(m_pairs_mutex);
168 unsigned int numPairs = m_pairs.size();
170 if (pair_index < 0) {
171 unsigned int index;
172 for (index = 0; index < numPairs; ++index)
173 s->Printf("[%d] \"%s\" -> \"%s\"\n", index,
174 m_pairs[index].first.GetCString(),
175 m_pairs[index].second.GetCString());
176 } else {
177 if (static_cast<unsigned int>(pair_index) < numPairs)
178 s->Printf("%s -> %s", m_pairs[pair_index].first.GetCString(),
179 m_pairs[pair_index].second.GetCString());
183 llvm::json::Value PathMappingList::ToJSON() {
184 llvm::json::Array entries;
185 std::lock_guard<std::mutex> lock(m_pairs_mutex);
186 for (const auto &pair : m_pairs) {
187 llvm::json::Array entry{pair.first.GetStringRef().str(),
188 pair.second.GetStringRef().str()};
189 entries.emplace_back(std::move(entry));
191 return entries;
194 void PathMappingList::Clear(bool notify) {
196 std::lock_guard<std::mutex> lock(m_pairs_mutex);
197 if (!m_pairs.empty())
198 ++m_mod_id;
199 m_pairs.clear();
201 Notify(notify);
204 bool PathMappingList::RemapPath(ConstString path,
205 ConstString &new_path) const {
206 if (std::optional<FileSpec> remapped = RemapPath(path.GetStringRef())) {
207 new_path.SetString(remapped->GetPath());
208 return true;
210 return false;
213 /// Append components to path, applying style.
214 static void AppendPathComponents(FileSpec &path, llvm::StringRef components,
215 llvm::sys::path::Style style) {
216 auto component = llvm::sys::path::begin(components, style);
217 auto e = llvm::sys::path::end(components);
218 while (component != e &&
219 llvm::sys::path::is_separator(*component->data(), style))
220 ++component;
221 for (; component != e; ++component)
222 path.AppendPathComponent(*component);
225 std::optional<FileSpec> PathMappingList::RemapPath(llvm::StringRef mapping_path,
226 bool only_if_exists) const {
227 std::lock_guard<std::mutex> lock(m_pairs_mutex);
228 if (m_pairs.empty() || mapping_path.empty())
229 return {};
230 LazyBool path_is_relative = eLazyBoolCalculate;
232 for (const auto &it : m_pairs) {
233 llvm::StringRef prefix = it.first.GetStringRef();
234 // We create a copy of mapping_path because StringRef::consume_from
235 // effectively modifies the instance itself.
236 llvm::StringRef path = mapping_path;
237 if (!path.consume_front(prefix)) {
238 // Relative paths won't have a leading "./" in them unless "." is the
239 // only thing in the relative path so we need to work around "."
240 // carefully.
241 if (prefix != ".")
242 continue;
243 // We need to figure out if the "path" argument is relative. If it is,
244 // then we should remap, else skip this entry.
245 if (path_is_relative == eLazyBoolCalculate) {
246 path_is_relative =
247 FileSpec(path).IsRelative() ? eLazyBoolYes : eLazyBoolNo;
249 if (!path_is_relative)
250 continue;
252 FileSpec remapped(it.second.GetStringRef());
253 auto orig_style = FileSpec::GuessPathStyle(prefix).value_or(
254 llvm::sys::path::Style::native);
255 AppendPathComponents(remapped, path, orig_style);
256 if (!only_if_exists || FileSystem::Instance().Exists(remapped))
257 return remapped;
259 return {};
262 std::optional<llvm::StringRef>
263 PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const {
264 std::string path = file.GetPath();
265 llvm::StringRef path_ref(path);
266 std::lock_guard<std::mutex> lock(m_pairs_mutex);
267 for (const auto &it : m_pairs) {
268 llvm::StringRef removed_prefix = it.second.GetStringRef();
269 if (!path_ref.consume_front(it.second.GetStringRef()))
270 continue;
271 auto orig_file = it.first.GetStringRef();
272 auto orig_style = FileSpec::GuessPathStyle(orig_file).value_or(
273 llvm::sys::path::Style::native);
274 fixed.SetFile(orig_file, orig_style);
275 AppendPathComponents(fixed, path_ref, orig_style);
276 return removed_prefix;
278 return std::nullopt;
281 std::optional<FileSpec>
282 PathMappingList::FindFile(const FileSpec &orig_spec) const {
283 // We must normalize the orig_spec again using the host's path style,
284 // otherwise there will be mismatch between the host and remote platform
285 // if they use different path styles.
286 if (auto remapped = RemapPath(NormalizePath(orig_spec.GetPath()),
287 /*only_if_exists=*/true))
288 return remapped;
290 return {};
293 bool PathMappingList::Replace(llvm::StringRef path, llvm::StringRef new_path,
294 bool notify) {
296 std::lock_guard<std::mutex> lock(m_pairs_mutex);
297 uint32_t idx = FindIndexForPathNoLock(path);
298 if (idx >= m_pairs.size())
299 return false;
300 ++m_mod_id;
301 m_pairs[idx].second = ConstString(new_path);
303 Notify(notify);
304 return true;
307 bool PathMappingList::Remove(ConstString path, bool notify) {
309 std::lock_guard<std::mutex> lock(m_pairs_mutex);
310 iterator pos = FindIteratorForPath(path);
311 if (pos == m_pairs.end())
312 return false;
314 ++m_mod_id;
315 m_pairs.erase(pos);
317 Notify(notify);
318 return true;
321 PathMappingList::const_iterator
322 PathMappingList::FindIteratorForPath(ConstString path) const {
323 std::lock_guard<std::mutex> lock(m_pairs_mutex);
324 const_iterator pos;
325 const_iterator begin = m_pairs.begin();
326 const_iterator end = m_pairs.end();
328 for (pos = begin; pos != end; ++pos) {
329 if (pos->first == path)
330 break;
332 return pos;
335 PathMappingList::iterator
336 PathMappingList::FindIteratorForPath(ConstString path) {
337 std::lock_guard<std::mutex> lock(m_pairs_mutex);
338 iterator pos;
339 iterator begin = m_pairs.begin();
340 iterator end = m_pairs.end();
342 for (pos = begin; pos != end; ++pos) {
343 if (pos->first == path)
344 break;
346 return pos;
349 bool PathMappingList::GetPathsAtIndex(uint32_t idx, ConstString &path,
350 ConstString &new_path) const {
351 std::lock_guard<std::mutex> lock(m_pairs_mutex);
352 if (idx < m_pairs.size()) {
353 path = m_pairs[idx].first;
354 new_path = m_pairs[idx].second;
355 return true;
357 return false;
360 uint32_t
361 PathMappingList::FindIndexForPathNoLock(llvm::StringRef orig_path) const {
362 const ConstString path = ConstString(NormalizePath(orig_path));
363 const_iterator pos;
364 const_iterator begin = m_pairs.begin();
365 const_iterator end = m_pairs.end();
367 for (pos = begin; pos != end; ++pos) {
368 if (pos->first == path)
369 return std::distance(begin, pos);
371 return UINT32_MAX;