130fdc8d8SChris Lattner //===-- PathMappingList.cpp -------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner // C Includes 1130fdc8d8SChris Lattner // C++ Includes 129394d772SEugene Zelenko #include <climits> 139394d772SEugene Zelenko #include <cstring> 149394d772SEugene Zelenko 1530fdc8d8SChris Lattner // Other libraries and framework includes 16d804d285SGreg Clayton // Project includes 1730fdc8d8SChris Lattner #include "lldb/Core/Error.h" 1830fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 19d804d285SGreg Clayton #include "lldb/Host/FileSpec.h" 20f343968fSZachary Turner #include "lldb/Host/PosixApi.h" 2148862d45SEli Friedman #include "lldb/Target/PathMappingList.h" 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner using namespace lldb; 2430fdc8d8SChris Lattner using namespace lldb_private; 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner //---------------------------------------------------------------------- 2730fdc8d8SChris Lattner // PathMappingList constructor 2830fdc8d8SChris Lattner //---------------------------------------------------------------------- 29*b9c1b51eSKate Stone PathMappingList::PathMappingList() 30*b9c1b51eSKate Stone : m_pairs(), m_callback(nullptr), m_callback_baton(nullptr), m_mod_id(0) {} 31d804d285SGreg Clayton 32*b9c1b51eSKate Stone PathMappingList::PathMappingList(ChangedCallback callback, void *callback_baton) 33*b9c1b51eSKate Stone : m_pairs(), m_callback(callback), m_callback_baton(callback_baton), 34*b9c1b51eSKate Stone m_mod_id(0) {} 3530fdc8d8SChris Lattner 36*b9c1b51eSKate Stone PathMappingList::PathMappingList(const PathMappingList &rhs) 37*b9c1b51eSKate Stone : m_pairs(rhs.m_pairs), m_callback(nullptr), m_callback_baton(nullptr), 38*b9c1b51eSKate Stone m_mod_id(0) {} 397e14f91dSGreg Clayton 40*b9c1b51eSKate Stone const PathMappingList &PathMappingList::operator=(const PathMappingList &rhs) { 41*b9c1b51eSKate Stone if (this != &rhs) { 427e14f91dSGreg Clayton m_pairs = rhs.m_pairs; 439394d772SEugene Zelenko m_callback = nullptr; 449394d772SEugene Zelenko m_callback_baton = nullptr; 454a89501fSGreg Clayton m_mod_id = rhs.m_mod_id; 467e14f91dSGreg Clayton } 477e14f91dSGreg Clayton return *this; 487e14f91dSGreg Clayton } 497e14f91dSGreg Clayton 509394d772SEugene Zelenko PathMappingList::~PathMappingList() = default; 5130fdc8d8SChris Lattner 52*b9c1b51eSKate Stone void PathMappingList::Append(const ConstString &path, 53*b9c1b51eSKate Stone const ConstString &replacement, bool notify) { 544a89501fSGreg Clayton ++m_mod_id; 5530fdc8d8SChris Lattner m_pairs.push_back(pair(path, replacement)); 5630fdc8d8SChris Lattner if (notify && m_callback) 5730fdc8d8SChris Lattner m_callback(*this, m_callback_baton); 5830fdc8d8SChris Lattner } 5930fdc8d8SChris Lattner 60*b9c1b51eSKate Stone void PathMappingList::Append(const PathMappingList &rhs, bool notify) { 614a89501fSGreg Clayton ++m_mod_id; 62*b9c1b51eSKate Stone if (!rhs.m_pairs.empty()) { 63d804d285SGreg Clayton const_iterator pos, end = rhs.m_pairs.end(); 64d804d285SGreg Clayton for (pos = rhs.m_pairs.begin(); pos != end; ++pos) 65d804d285SGreg Clayton m_pairs.push_back(*pos); 66d804d285SGreg Clayton if (notify && m_callback) 67d804d285SGreg Clayton m_callback(*this, m_callback_baton); 68d804d285SGreg Clayton } 69d804d285SGreg Clayton } 70d804d285SGreg Clayton 71*b9c1b51eSKate Stone void PathMappingList::Insert(const ConstString &path, 72*b9c1b51eSKate Stone const ConstString &replacement, uint32_t index, 73*b9c1b51eSKate Stone bool notify) { 744a89501fSGreg Clayton ++m_mod_id; 7530fdc8d8SChris Lattner iterator insert_iter; 7630fdc8d8SChris Lattner if (index >= m_pairs.size()) 7730fdc8d8SChris Lattner insert_iter = m_pairs.end(); 7830fdc8d8SChris Lattner else 7930fdc8d8SChris Lattner insert_iter = m_pairs.begin() + index; 8030fdc8d8SChris Lattner m_pairs.insert(insert_iter, pair(path, replacement)); 8130fdc8d8SChris Lattner if (notify && m_callback) 8230fdc8d8SChris Lattner m_callback(*this, m_callback_baton); 8330fdc8d8SChris Lattner } 8430fdc8d8SChris Lattner 85*b9c1b51eSKate Stone bool PathMappingList::Replace(const ConstString &path, 86*b9c1b51eSKate Stone const ConstString &replacement, uint32_t index, 87*b9c1b51eSKate Stone bool notify) { 8867cc0636SGreg Clayton iterator insert_iter; 8967cc0636SGreg Clayton if (index >= m_pairs.size()) 9067cc0636SGreg Clayton return false; 914a89501fSGreg Clayton ++m_mod_id; 9267cc0636SGreg Clayton m_pairs[index] = pair(path, replacement); 9367cc0636SGreg Clayton if (notify && m_callback) 9467cc0636SGreg Clayton m_callback(*this, m_callback_baton); 9567cc0636SGreg Clayton return true; 9667cc0636SGreg Clayton } 9767cc0636SGreg Clayton 98*b9c1b51eSKate Stone bool PathMappingList::Remove(size_t index, bool notify) { 99a746e8e5SZachary Turner if (index >= m_pairs.size()) 10030fdc8d8SChris Lattner return false; 10130fdc8d8SChris Lattner 1024a89501fSGreg Clayton ++m_mod_id; 10330fdc8d8SChris Lattner iterator iter = m_pairs.begin() + index; 10430fdc8d8SChris Lattner m_pairs.erase(iter); 10530fdc8d8SChris Lattner if (notify && m_callback) 10630fdc8d8SChris Lattner m_callback(*this, m_callback_baton); 10730fdc8d8SChris Lattner return true; 10830fdc8d8SChris Lattner } 10930fdc8d8SChris Lattner 11064bab489SJohnny Chen // For clients which do not need the pair index dumped, pass a pair_index >= 0 11164bab489SJohnny Chen // to only dump the indicated pair. 112*b9c1b51eSKate Stone void PathMappingList::Dump(Stream *s, int pair_index) { 11330fdc8d8SChris Lattner unsigned int numPairs = m_pairs.size(); 11430fdc8d8SChris Lattner 115*b9c1b51eSKate Stone if (pair_index < 0) { 11664bab489SJohnny Chen unsigned int index; 11764bab489SJohnny Chen for (index = 0; index < numPairs; ++index) 118*b9c1b51eSKate Stone s->Printf("[%d] \"%s\" -> \"%s\"\n", index, 119*b9c1b51eSKate Stone m_pairs[index].first.GetCString(), 120*b9c1b51eSKate Stone m_pairs[index].second.GetCString()); 121*b9c1b51eSKate Stone } else { 1223985c8c6SSaleem Abdulrasool if (static_cast<unsigned int>(pair_index) < numPairs) 123*b9c1b51eSKate Stone s->Printf("%s -> %s", m_pairs[pair_index].first.GetCString(), 124*b9c1b51eSKate Stone m_pairs[pair_index].second.GetCString()); 12564bab489SJohnny Chen } 12630fdc8d8SChris Lattner } 12730fdc8d8SChris Lattner 128*b9c1b51eSKate Stone void PathMappingList::Clear(bool notify) { 1294a89501fSGreg Clayton if (!m_pairs.empty()) 1304a89501fSGreg Clayton ++m_mod_id; 13130fdc8d8SChris Lattner m_pairs.clear(); 13230fdc8d8SChris Lattner if (notify && m_callback) 13330fdc8d8SChris Lattner m_callback(*this, m_callback_baton); 13430fdc8d8SChris Lattner } 13530fdc8d8SChris Lattner 136*b9c1b51eSKate Stone bool PathMappingList::RemapPath(const ConstString &path, 137*b9c1b51eSKate Stone ConstString &new_path) const { 138f601503aSSean Callanan const char *path_cstr = path.GetCString(); 139f601503aSSean Callanan 140f601503aSSean Callanan if (!path_cstr) 141f601503aSSean Callanan return false; 142f601503aSSean Callanan 14330fdc8d8SChris Lattner const_iterator pos, end = m_pairs.end(); 144*b9c1b51eSKate Stone for (pos = m_pairs.begin(); pos != end; ++pos) { 14530fdc8d8SChris Lattner const size_t prefixLen = pos->first.GetLength(); 14630fdc8d8SChris Lattner 147*b9c1b51eSKate Stone if (::strncmp(pos->first.GetCString(), path_cstr, prefixLen) == 0) { 14830fdc8d8SChris Lattner std::string new_path_str(pos->second.GetCString()); 14930fdc8d8SChris Lattner new_path_str.append(path.GetCString() + prefixLen); 15030fdc8d8SChris Lattner new_path.SetCString(new_path_str.c_str()); 15130fdc8d8SChris Lattner return true; 15230fdc8d8SChris Lattner } 15330fdc8d8SChris Lattner } 15430fdc8d8SChris Lattner return false; 15530fdc8d8SChris Lattner } 1567e14f91dSGreg Clayton 157*b9c1b51eSKate Stone bool PathMappingList::RemapPath(const char *path, std::string &new_path) const { 1589394d772SEugene Zelenko if (m_pairs.empty() || path == nullptr || path[0] == '\0') 159f9be6933SGreg Clayton return false; 160f9be6933SGreg Clayton 161f9be6933SGreg Clayton const_iterator pos, end = m_pairs.end(); 162*b9c1b51eSKate Stone for (pos = m_pairs.begin(); pos != end; ++pos) { 163f9be6933SGreg Clayton const size_t prefix_len = pos->first.GetLength(); 164f9be6933SGreg Clayton 165*b9c1b51eSKate Stone if (::strncmp(pos->first.GetCString(), path, prefix_len) == 0) { 166f9be6933SGreg Clayton new_path = pos->second.GetCString(); 167f9be6933SGreg Clayton new_path.append(path + prefix_len); 168f9be6933SGreg Clayton return true; 169f9be6933SGreg Clayton } 170f9be6933SGreg Clayton } 171f9be6933SGreg Clayton return false; 172f9be6933SGreg Clayton } 173f9be6933SGreg Clayton 174*b9c1b51eSKate Stone bool PathMappingList::ReverseRemapPath(const ConstString &path, 175*b9c1b51eSKate Stone ConstString &new_path) const { 176b0b1ea36STamas Berghammer const char *path_cstr = path.GetCString(); 177b0b1ea36STamas Berghammer if (!path_cstr) 178b0b1ea36STamas Berghammer return false; 179b0b1ea36STamas Berghammer 180*b9c1b51eSKate Stone for (const auto &it : m_pairs) { 181291fd350SJim Ingham // FIXME: This should be using FileSpec API's to do the path appending. 182b0b1ea36STamas Berghammer const size_t prefixLen = it.second.GetLength(); 183*b9c1b51eSKate Stone if (::strncmp(it.second.GetCString(), path_cstr, prefixLen) == 0) { 184b0b1ea36STamas Berghammer std::string new_path_str(it.first.GetCString()); 185b0b1ea36STamas Berghammer new_path_str.append(path.GetCString() + prefixLen); 186b0b1ea36STamas Berghammer new_path.SetCString(new_path_str.c_str()); 187b0b1ea36STamas Berghammer return true; 188b0b1ea36STamas Berghammer } 189b0b1ea36STamas Berghammer } 190b0b1ea36STamas Berghammer return false; 191b0b1ea36STamas Berghammer } 192b0b1ea36STamas Berghammer 193*b9c1b51eSKate Stone bool PathMappingList::FindFile(const FileSpec &orig_spec, 194*b9c1b51eSKate Stone FileSpec &new_spec) const { 195*b9c1b51eSKate Stone if (!m_pairs.empty()) { 196d804d285SGreg Clayton char orig_path[PATH_MAX]; 197*b9c1b51eSKate Stone const size_t orig_path_len = 198*b9c1b51eSKate Stone orig_spec.GetPath(orig_path, sizeof(orig_path)); 199*b9c1b51eSKate Stone if (orig_path_len > 0) { 200d804d285SGreg Clayton const_iterator pos, end = m_pairs.end(); 201*b9c1b51eSKate Stone for (pos = m_pairs.begin(); pos != end; ++pos) { 202d804d285SGreg Clayton const size_t prefix_len = pos->first.GetLength(); 203d804d285SGreg Clayton 204*b9c1b51eSKate Stone if (orig_path_len >= prefix_len) { 205*b9c1b51eSKate Stone if (::strncmp(pos->first.GetCString(), orig_path, prefix_len) == 0) { 206291fd350SJim Ingham new_spec.SetFile(pos->second.GetCString(), false); 207291fd350SJim Ingham new_spec.AppendPathComponent(orig_path + prefix_len); 208d804d285SGreg Clayton if (new_spec.Exists()) 209d804d285SGreg Clayton return true; 210d804d285SGreg Clayton } 211d804d285SGreg Clayton } 212d804d285SGreg Clayton } 213d804d285SGreg Clayton } 214d804d285SGreg Clayton } 215d804d285SGreg Clayton new_spec.Clear(); 216d804d285SGreg Clayton return false; 217d804d285SGreg Clayton } 218d804d285SGreg Clayton 219*b9c1b51eSKate Stone bool PathMappingList::Replace(const ConstString &path, 220*b9c1b51eSKate Stone const ConstString &new_path, bool notify) { 2217e14f91dSGreg Clayton uint32_t idx = FindIndexForPath(path); 222*b9c1b51eSKate Stone if (idx < m_pairs.size()) { 2234a89501fSGreg Clayton ++m_mod_id; 2247e14f91dSGreg Clayton m_pairs[idx].second = new_path; 2257e14f91dSGreg Clayton if (notify && m_callback) 2267e14f91dSGreg Clayton m_callback(*this, m_callback_baton); 2277e14f91dSGreg Clayton return true; 2287e14f91dSGreg Clayton } 2297e14f91dSGreg Clayton return false; 2307e14f91dSGreg Clayton } 2317e14f91dSGreg Clayton 232*b9c1b51eSKate Stone bool PathMappingList::Remove(const ConstString &path, bool notify) { 2337e14f91dSGreg Clayton iterator pos = FindIteratorForPath(path); 234*b9c1b51eSKate Stone if (pos != m_pairs.end()) { 2354a89501fSGreg Clayton ++m_mod_id; 2367e14f91dSGreg Clayton m_pairs.erase(pos); 2377e14f91dSGreg Clayton if (notify && m_callback) 2387e14f91dSGreg Clayton m_callback(*this, m_callback_baton); 2397e14f91dSGreg Clayton return true; 2407e14f91dSGreg Clayton } 2417e14f91dSGreg Clayton return false; 2427e14f91dSGreg Clayton } 2437e14f91dSGreg Clayton 2447e14f91dSGreg Clayton PathMappingList::const_iterator 245*b9c1b51eSKate Stone PathMappingList::FindIteratorForPath(const ConstString &path) const { 2467e14f91dSGreg Clayton const_iterator pos; 2477e14f91dSGreg Clayton const_iterator begin = m_pairs.begin(); 2487e14f91dSGreg Clayton const_iterator end = m_pairs.end(); 2497e14f91dSGreg Clayton 250*b9c1b51eSKate Stone for (pos = begin; pos != end; ++pos) { 2517e14f91dSGreg Clayton if (pos->first == path) 2527e14f91dSGreg Clayton break; 2537e14f91dSGreg Clayton } 2547e14f91dSGreg Clayton return pos; 2557e14f91dSGreg Clayton } 2567e14f91dSGreg Clayton 2577e14f91dSGreg Clayton PathMappingList::iterator 258*b9c1b51eSKate Stone PathMappingList::FindIteratorForPath(const ConstString &path) { 2597e14f91dSGreg Clayton iterator pos; 2607e14f91dSGreg Clayton iterator begin = m_pairs.begin(); 2617e14f91dSGreg Clayton iterator end = m_pairs.end(); 2627e14f91dSGreg Clayton 263*b9c1b51eSKate Stone for (pos = begin; pos != end; ++pos) { 2647e14f91dSGreg Clayton if (pos->first == path) 2657e14f91dSGreg Clayton break; 2667e14f91dSGreg Clayton } 2677e14f91dSGreg Clayton return pos; 2687e14f91dSGreg Clayton } 2697e14f91dSGreg Clayton 270*b9c1b51eSKate Stone bool PathMappingList::GetPathsAtIndex(uint32_t idx, ConstString &path, 271*b9c1b51eSKate Stone ConstString &new_path) const { 272*b9c1b51eSKate Stone if (idx < m_pairs.size()) { 2737e14f91dSGreg Clayton path = m_pairs[idx].first; 2747e14f91dSGreg Clayton new_path = m_pairs[idx].second; 2757e14f91dSGreg Clayton return true; 2767e14f91dSGreg Clayton } 2777e14f91dSGreg Clayton return false; 2787e14f91dSGreg Clayton } 2797e14f91dSGreg Clayton 280*b9c1b51eSKate Stone uint32_t PathMappingList::FindIndexForPath(const ConstString &path) const { 2817e14f91dSGreg Clayton const_iterator pos; 2827e14f91dSGreg Clayton const_iterator begin = m_pairs.begin(); 2837e14f91dSGreg Clayton const_iterator end = m_pairs.end(); 2847e14f91dSGreg Clayton 285*b9c1b51eSKate Stone for (pos = begin; pos != end; ++pos) { 2867e14f91dSGreg Clayton if (pos->first == path) 2877e14f91dSGreg Clayton return std::distance(begin, pos); 2887e14f91dSGreg Clayton } 2897e14f91dSGreg Clayton return UINT32_MAX; 2907e14f91dSGreg Clayton } 291