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