1 | //===-- PathMappingList.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_TARGET_PATHMAPPINGLIST_H |
10 | #define LLDB_TARGET_PATHMAPPINGLIST_H |
11 | |
12 | #include "lldb/Utility/ConstString.h" |
13 | #include "lldb/Utility/Status.h" |
14 | #include "llvm/Support/Error.h" |
15 | #include "llvm/Support/JSON.h" |
16 | #include <map> |
17 | #include <mutex> |
18 | #include <optional> |
19 | #include <vector> |
20 | |
21 | namespace lldb_private { |
22 | |
23 | class PathMappingList { |
24 | public: |
25 | typedef void (*ChangedCallback)(const PathMappingList &path_list, |
26 | void *baton); |
27 | |
28 | // Constructors and Destructors |
29 | PathMappingList(); |
30 | |
31 | PathMappingList(ChangedCallback callback, void *callback_baton); |
32 | |
33 | PathMappingList(const PathMappingList &rhs); |
34 | |
35 | ~PathMappingList(); |
36 | |
37 | const PathMappingList &operator=(const PathMappingList &rhs); |
38 | |
39 | void Append(llvm::StringRef path, llvm::StringRef replacement, bool notify); |
40 | |
41 | void Append(const PathMappingList &rhs, bool notify); |
42 | |
43 | /// Append <path, replacement> pair without duplication. |
44 | /// \return whether appending suceeds without duplication or not. |
45 | bool AppendUnique(llvm::StringRef path, llvm::StringRef replacement, |
46 | bool notify); |
47 | |
48 | void Clear(bool notify); |
49 | |
50 | // By default, dump all pairs. |
51 | void Dump(Stream *s, int pair_index = -1); |
52 | |
53 | llvm::json::Value ToJSON(); |
54 | |
55 | bool IsEmpty() const { |
56 | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
57 | return m_pairs.empty(); |
58 | } |
59 | |
60 | size_t GetSize() const { |
61 | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
62 | return m_pairs.size(); |
63 | } |
64 | |
65 | bool GetPathsAtIndex(uint32_t idx, ConstString &path, |
66 | ConstString &new_path) const; |
67 | |
68 | void Insert(llvm::StringRef path, llvm::StringRef replacement, |
69 | uint32_t insert_idx, bool notify); |
70 | |
71 | bool Remove(size_t index, bool notify); |
72 | |
73 | bool Remove(ConstString path, bool notify); |
74 | |
75 | bool Replace(llvm::StringRef path, llvm::StringRef replacement, bool notify); |
76 | |
77 | bool Replace(llvm::StringRef path, llvm::StringRef replacement, |
78 | uint32_t index, bool notify); |
79 | bool RemapPath(ConstString path, ConstString &new_path) const; |
80 | |
81 | /// Remaps a source file given \a path into \a new_path. |
82 | /// |
83 | /// Remaps \a path if any source remappings match. This function |
84 | /// does NOT stat the file system so it can be used in tight loops |
85 | /// where debug info is being parsed. |
86 | /// |
87 | /// \param[in] path |
88 | /// The original source file path to try and remap. |
89 | /// |
90 | /// \param[in] only_if_exists |
91 | /// If \b true, besides matching \p path with the remapping rules, this |
92 | /// tries to check with the filesystem that the remapped file exists. If |
93 | /// no valid file is found, \b std::nullopt is returned. This might be |
94 | /// expensive, specially on a network. |
95 | /// |
96 | /// If \b false, then the existence of the returned remapping is not |
97 | /// checked. |
98 | /// |
99 | /// \return |
100 | /// The remapped filespec that may or may not exist on disk. |
101 | std::optional<FileSpec> RemapPath(llvm::StringRef path, |
102 | bool only_if_exists = false) const; |
103 | bool RemapPath(const char *, std::string &) const = delete; |
104 | |
105 | /// Perform reverse source path remap for input \a file. |
106 | /// Source maps contains a list of <from_original_path, to_new_path> mappings. |
107 | /// Reverse remap means locating a matching entry prefix using "to_new_path" |
108 | /// part and replacing it with "from_original_path" part if found. |
109 | /// |
110 | /// \param[in] file |
111 | /// The source path to reverse remap. |
112 | /// \param[in] fixed |
113 | /// The reversed mapped new path. |
114 | /// |
115 | /// \return |
116 | /// std::nullopt if no remapping happens, otherwise, the matching source |
117 | /// map entry's ""to_new_pathto"" part (which is the prefix of \a file) is |
118 | /// returned. |
119 | std::optional<llvm::StringRef> ReverseRemapPath(const FileSpec &file, |
120 | FileSpec &fixed) const; |
121 | |
122 | /// Finds a source file given a file spec using the path remappings. |
123 | /// |
124 | /// Tries to resolve \a orig_spec by checking the path remappings. |
125 | /// It makes sure the file exists by checking with the file system, |
126 | /// so this call can be expensive if the remappings are on a network |
127 | /// or are even on the local file system, so use this function |
128 | /// sparingly (not in a tight debug info parsing loop). |
129 | /// |
130 | /// \param[in] orig_spec |
131 | /// The original source file path to try and remap. |
132 | /// |
133 | /// \return |
134 | /// The newly remapped filespec that is guaranteed to exist. |
135 | std::optional<FileSpec> FindFile(const FileSpec &orig_spec) const; |
136 | |
137 | uint32_t FindIndexForPath(llvm::StringRef path) const; |
138 | |
139 | uint32_t GetModificationID() const { |
140 | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
141 | return m_mod_id; |
142 | } |
143 | |
144 | protected: |
145 | mutable std::recursive_mutex m_mutex; |
146 | typedef std::pair<ConstString, ConstString> pair; |
147 | typedef std::vector<pair> collection; |
148 | typedef collection::iterator iterator; |
149 | typedef collection::const_iterator const_iterator; |
150 | |
151 | iterator FindIteratorForPath(ConstString path); |
152 | |
153 | const_iterator FindIteratorForPath(ConstString path) const; |
154 | |
155 | collection m_pairs; |
156 | ChangedCallback m_callback = nullptr; |
157 | void *m_callback_baton = nullptr; |
158 | uint32_t m_mod_id = 0; // Incremented anytime anything is added or removed. |
159 | }; |
160 | |
161 | } // namespace lldb_private |
162 | |
163 | #endif // LLDB_TARGET_PATHMAPPINGLIST_H |
164 | |