This revision was automatically updated to reflect the committed changes.
Closed by commit rL332842: Fix PathMappingList for relative and empty paths
after recent FileSpec… (authored by gclayton, committed by ).
Herald added a subscriber: llvm-commits.
Changed prior to commit:
https://reviews.llvm.org/D47021?vs=147587&id=147780#toc
Repository:
rL LLVM
https://reviews.llvm.org/D47021
Files:
lldb/trunk/include/lldb/Target/PathMappingList.h
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/source/Target/PathMappingList.cpp
lldb/trunk/source/Target/Target.cpp
lldb/trunk/source/Utility/FileSpec.cpp
lldb/trunk/unittests/Target/CMakeLists.txt
lldb/trunk/unittests/Target/PathMappingListTest.cpp
lldb/trunk/unittests/Utility/FileSpecTest.cpp
Index: lldb/trunk/source/Target/Target.cpp
===================================================================
--- lldb/trunk/source/Target/Target.cpp
+++ lldb/trunk/source/Target/Target.cpp
@@ -328,11 +328,7 @@
bool hardware,
LazyBool move_to_nearest_code) {
FileSpec remapped_file;
- ConstString remapped_path;
- if (GetSourcePathMap().ReverseRemapPath(ConstString(file.GetPath().c_str()),
- remapped_path))
- remapped_file.SetFile(remapped_path.AsCString(), false);
- else
+ if (!GetSourcePathMap().ReverseRemapPath(file, remapped_file))
remapped_file = file;
if (check_inlines == eLazyBoolCalculate) {
Index: lldb/trunk/source/Target/PathMappingList.cpp
===================================================================
--- lldb/trunk/source/Target/PathMappingList.cpp
+++ lldb/trunk/source/Target/PathMappingList.cpp
@@ -14,6 +14,7 @@
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-private-enumerations.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Target/PathMappingList.h"
#include "lldb/Utility/FileSpec.h"
@@ -23,6 +24,22 @@
using namespace lldb;
using namespace lldb_private;
+namespace {
+ // We must normalize our path pairs that we store because if we don't then
+ // things won't always work. We found a case where if we did:
+ // (lldb) settings set target.source-map . /tmp
+ // We would store a path pairs of "." and "/tmp" as raw strings. If the debug
+ // info contains "./foo/bar.c", the path will get normalized to "foo/bar.c".
+ // When PathMappingList::RemapPath() is called, it expects the path to start
+ // with the raw path pair, which doesn't work anymore because the paths have
+ // been normalized when the debug info was loaded. So we need to store
+ // nomalized path pairs to ensure things match up.
+ ConstString NormalizePath(const ConstString &path) {
+ // If we use "path" to construct a FileSpec, it will normalize the path for
+ // us. We then grab the string and turn it back into a ConstString.
+ return ConstString(FileSpec(path.GetStringRef(), false).GetPath());
+ }
+}
//----------------------------------------------------------------------
// PathMappingList constructor
//----------------------------------------------------------------------
@@ -52,7 +69,7 @@
void PathMappingList::Append(const ConstString &path,
const ConstString &replacement, bool notify) {
++m_mod_id;
- m_pairs.push_back(pair(path, replacement));
+ m_pairs.emplace_back(pair(NormalizePath(path), NormalizePath(replacement)));
if (notify && m_callback)
m_callback(*this, m_callback_baton);
}
@@ -77,7 +94,8 @@
insert_iter = m_pairs.end();
else
insert_iter = m_pairs.begin() + index;
- m_pairs.insert(insert_iter, pair(path, replacement));
+ m_pairs.emplace(insert_iter, pair(NormalizePath(path),
+ NormalizePath(replacement)));
if (notify && m_callback)
m_callback(*this, m_callback_baton);
}
@@ -88,7 +106,7 @@
if (index >= m_pairs.size())
return false;
++m_mod_id;
- m_pairs[index] = pair(path, replacement);
+ m_pairs[index] = pair(NormalizePath(path), NormalizePath(replacement));
if (notify && m_callback)
m_callback(*this, m_callback_baton);
return true;
@@ -134,58 +152,53 @@
bool PathMappingList::RemapPath(const ConstString &path,
ConstString &new_path) const {
- const char *path_cstr = path.GetCString();
- // CLEANUP: Convert this function to use StringRefs internally instead
- // of raw c-strings.
- if (!path_cstr)
- return false;
-
- const_iterator pos, end = m_pairs.end();
- for (pos = m_pairs.begin(); pos != end; ++pos) {
- const size_t prefixLen = pos->first.GetLength();
-
- if (::strncmp(pos->first.GetCString(), path_cstr, prefixLen) == 0) {
- std::string new_path_str(pos->second.GetCString());
- new_path_str.append(path.GetCString() + prefixLen);
- new_path.SetCString(new_path_str.c_str());
- return true;
- }
+ std::string remapped;
+ if (RemapPath(path.GetStringRef(), remapped)) {
+ new_path.SetString(remapped);
+ return true;
}
return false;
}
bool PathMappingList::RemapPath(llvm::StringRef path,
std::string &new_path) const {
if (m_pairs.empty() || path.empty())
return false;
-
- const_iterator pos, end = m_pairs.end();
- for (pos = m_pairs.begin(); pos != end; ++pos) {
- if (!path.consume_front(pos->first.GetStringRef()))
- continue;
-
- new_path = pos->second.GetStringRef();
- new_path.append(path);
+ LazyBool path_is_relative = eLazyBoolCalculate;
+ for (const auto &it : m_pairs) {
+ auto prefix = it.first.GetStringRef();
+ if (!path.consume_front(prefix)) {
+ // Relative paths won't have a leading "./" in them unless "." is the
+ // only thing in the relative path so we need to work around "."
+ // carefully.
+ if (prefix != ".")
+ continue;
+ // We need to figure out if the "path" argument is relative. If it is,
+ // then we should remap, else skip this entry.
+ if (path_is_relative == eLazyBoolCalculate) {
+ path_is_relative = FileSpec(path, false).IsRelative() ? eLazyBoolYes :
+ eLazyBoolNo;
+ }
+ if (!path_is_relative)
+ continue;
+ }
+ FileSpec remapped(it.second.GetStringRef(), false);
+ remapped.AppendPathComponent(path);
+ new_path = remapped.GetPath();
return true;
}
return false;
}
-bool PathMappingList::ReverseRemapPath(const ConstString &path,
- ConstString &new_path) const {
- const char *path_cstr = path.GetCString();
- if (!path_cstr)
- return false;
-
+bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const {
+ std::string path = file.GetPath();
+ llvm::StringRef path_ref(path);
for (const auto &it : m_pairs) {
- // FIXME: This should be using FileSpec API's to do the path appending.
- const size_t prefixLen = it.second.GetLength();
- if (::strncmp(it.second.GetCString(), path_cstr, prefixLen) == 0) {
- std::string new_path_str(it.first.GetCString());
- new_path_str.append(path.GetCString() + prefixLen);
- new_path.SetCString(new_path_str.c_str());
- return true;
- }
+ if (!path_ref.consume_front(it.second.GetStringRef()))
+ continue;
+ fixed.SetFile(it.first.GetStringRef(), false);
+ fixed.AppendPathComponent(path_ref);
+ return true;
}
return false;
}
@@ -277,7 +290,8 @@
return false;
}
-uint32_t PathMappingList::FindIndexForPath(const ConstString &path) const {
+uint32_t PathMappingList::FindIndexForPath(const ConstString &orig_path) const {
+ const ConstString path = NormalizePath(orig_path);
const_iterator pos;
const_iterator begin = m_pairs.begin();
const_iterator end = m_pairs.end();
Index: lldb/trunk/source/Utility/FileSpec.cpp
===================================================================
--- lldb/trunk/source/Utility/FileSpec.cpp
+++ lldb/trunk/source/Utility/FileSpec.cpp
@@ -67,6 +67,31 @@
std::replace(path.begin(), path.end(), '/', '\\');
}
+
+bool PathIsRelative(llvm::StringRef path, FileSpec::Style style) {
+
+ if (path.empty())
+ return false;
+
+ if (PathStyleIsPosix(style)) {
+ // If the path doesn't start with '/' or '~', return true
+ switch (path[0]) {
+ case '/':
+ case '~':
+ return false;
+ default:
+ return true;
+ }
+ } else {
+ if (path.size() >= 2 && path[1] == ':')
+ return false;
+ if (path[0] == '/')
+ return false;
+ return true;
+ }
+ return false;
+}
+
} // end anonymous namespace
void FileSpec::Resolve(llvm::SmallVectorImpl<char> &path) {
@@ -814,31 +839,10 @@
}
bool FileSpec::IsRelative() const {
- const char *dir = m_directory.GetCString();
- llvm::StringRef directory(dir ? dir : "");
-
- if (directory.size() > 0) {
- if (PathStyleIsPosix(m_style)) {
- // If the path doesn't start with '/' or '~', return true
- switch (directory[0]) {
- case '/':
- case '~':
- return false;
- default:
- return true;
- }
- } else {
- if (directory.size() >= 2 && directory[1] == ':')
- return false;
- if (directory[0] == '/')
- return false;
- return true;
- }
- } else if (m_filename) {
- // No directory, just a basename, return true
- return true;
- }
- return false;
+ if (m_directory)
+ return PathIsRelative(m_directory.GetStringRef(), m_style);
+ else
+ return PathIsRelative(m_filename.GetStringRef(), m_style);
}
bool FileSpec::IsAbsolute() const { return !FileSpec::IsRelative(); }
Index: lldb/trunk/include/lldb/Target/PathMappingList.h
===================================================================
--- lldb/trunk/include/lldb/Target/PathMappingList.h
+++ lldb/trunk/include/lldb/Target/PathMappingList.h
@@ -90,7 +90,7 @@
bool RemapPath(llvm::StringRef path, std::string &new_path) const;
bool RemapPath(const char *, std::string &) const = delete;
- bool ReverseRemapPath(const ConstString &path, ConstString &new_path) const;
+ bool ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const;
//------------------------------------------------------------------
/// Finds a source file given a file spec using the path remappings.
Index: lldb/trunk/lldb.xcodeproj/project.pbxproj
===================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj
@@ -267,6 +267,7 @@
26680336116005EF008E1FE4 /* SBBreakpointLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */; };
26680337116005F1008E1FE4 /* SBBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AF16A9C11402D5B007A7B3F /* SBBreakpoint.cpp */; };
2668035C11601108008E1FE4 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26680207115FD0ED008E1FE4 /* LLDB.framework */; };
+ 2668A2EE20AF417D00D94111 /* PathMappingListTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2668A2ED20AF417D00D94111 /* PathMappingListTest.cpp */; };
266942001A6DC2AC0063BE93 /* MICmdArgContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941601A6DC2AB0063BE93 /* MICmdArgContext.cpp */; };
266942011A6DC2AC0063BE93 /* MICmdArgSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941621A6DC2AB0063BE93 /* MICmdArgSet.cpp */; };
266942021A6DC2AC0063BE93 /* MICmdArgValBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941641A6DC2AB0063BE93 /* MICmdArgValBase.cpp */; };
@@ -1755,6 +1756,7 @@
2666ADC31B3CB675001FAFD3 /* HexagonDYLDRendezvous.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HexagonDYLDRendezvous.cpp; sourceTree = "<group>"; };
2666ADC41B3CB675001FAFD3 /* HexagonDYLDRendezvous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HexagonDYLDRendezvous.h; sourceTree = "<group>"; };
26680207115FD0ED008E1FE4 /* LLDB.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LLDB.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2668A2ED20AF417D00D94111 /* PathMappingListTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PathMappingListTest.cpp; path = Target/PathMappingListTest.cpp; sourceTree = "<group>"; };
2669415B1A6DC2AB0063BE93 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CMakeLists.txt; path = "tools/lldb-mi/CMakeLists.txt"; sourceTree = SOURCE_ROOT; };
2669415E1A6DC2AB0063BE93 /* lldb-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "lldb-Info.plist"; path = "tools/lldb-mi/lldb-Info.plist"; sourceTree = SOURCE_ROOT; };
2669415F1A6DC2AB0063BE93 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = "tools/lldb-mi/Makefile"; sourceTree = SOURCE_ROOT; };
@@ -6709,6 +6711,7 @@
children = (
9A2057061F3B818600F6C293 /* MemoryRegionInfoTest.cpp */,
AFAFD8091E57E1B90017A14F /* ModuleCacheTest.cpp */,
+ 2668A2ED20AF417D00D94111 /* PathMappingListTest.cpp */,
);
name = Target;
sourceTree = "<group>";
@@ -7351,6 +7354,7 @@
23CB15341D66DA9300EDDDE1 /* CPlusPlusLanguageTest.cpp in Sources */,
9A2057381F3B8E7E00F6C293 /* FileSystemTest.cpp in Sources */,
9A2057201F3B8D2500F6C293 /* UnixSignalsTest.cpp in Sources */,
+ 2668A2EE20AF417D00D94111 /* PathMappingListTest.cpp in Sources */,
AFAFD80A1E57E1B90017A14F /* ModuleCacheTest.cpp in Sources */,
9A3D43DA1F3151C400EB767C /* StructuredDataTest.cpp in Sources */,
9A2057121F3B824B00F6C293 /* SymbolFileDWARFTests.cpp in Sources */,
Index: lldb/trunk/unittests/Utility/FileSpecTest.cpp
===================================================================
--- lldb/trunk/unittests/Utility/FileSpecTest.cpp
+++ lldb/trunk/unittests/Utility/FileSpecTest.cpp
@@ -273,3 +273,50 @@
EXPECT_EQ("(empty)", llvm::formatv("{0:D}", F).str());
}
+TEST(FileSpecTest, IsRelative) {
+ llvm::StringRef not_relative[] = {
+ "/",
+ "/a",
+ "/a/",
+ "/a/b",
+ "/a/b/",
+ "//",
+ "//a",
+ "//a/",
+ "//a/b",
+ "//a/b/",
+ "~",
+ "~/",
+ "~/a",
+ "~/a/",
+ "~/a/b"
+ "~/a/b/",
+ "/foo/.",
+ "/foo/..",
+ "/foo/../",
+ "/foo/../.",
+ };
+ for (const auto &path: not_relative) {
+ FileSpec spec(path, false, FileSpec::Style::posix);
+ EXPECT_FALSE(spec.IsRelative());
+ }
+ llvm::StringRef is_relative[] = {
+ ".",
+ "./",
+ ".///",
+ "a",
+ "./a",
+ "./a/",
+ "./a/",
+ "./a/b",
+ "./a/b/",
+ "../foo",
+ "foo/bar.c",
+ "./foo/bar.c"
+ };
+ for (const auto &path: is_relative) {
+ FileSpec spec(path, false, FileSpec::Style::posix);
+ EXPECT_TRUE(spec.IsRelative());
+ }
+}
+
Index: lldb/trunk/unittests/Target/CMakeLists.txt
===================================================================
--- lldb/trunk/unittests/Target/CMakeLists.txt
+++ lldb/trunk/unittests/Target/CMakeLists.txt
@@ -1,6 +1,7 @@
add_lldb_unittest(TargetTests
MemoryRegionInfoTest.cpp
ModuleCacheTest.cpp
+ PathMappingListTest.cpp
LINK_LIBS
lldbCore
Index: lldb/trunk/unittests/Target/PathMappingListTest.cpp
===================================================================
--- lldb/trunk/unittests/Target/PathMappingListTest.cpp
+++ lldb/trunk/unittests/Target/PathMappingListTest.cpp
@@ -0,0 +1,109 @@
+//===-- PathMappingListTest.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ArrayRef.h"
+#include "lldb/Target/PathMappingList.h"
+#include "lldb/Utility/FileSpec.h"
+#include "gtest/gtest.h"
+#include <utility>
+
+using namespace lldb_private;
+
+namespace {
+ struct Matches {
+ ConstString original;
+ ConstString remapped;
+ Matches(const char *o, const char *r) : original(o),
+ remapped(r) {}
+ };
+
+ void TestPathMappings(const PathMappingList &map,
+ llvm::ArrayRef<Matches> matches,
+ llvm::ArrayRef<ConstString> fails) {
+ ConstString actual_remapped;
+ for (const auto &fail: fails) {
+ EXPECT_FALSE(map.RemapPath(fail, actual_remapped));
+ }
+ for (const auto &match: matches) {
+ FileSpec orig_spec(match.original.GetStringRef(), false);
+ std::string orig_normalized = orig_spec.GetPath();
+ EXPECT_TRUE(map.RemapPath(match.original, actual_remapped));
+ EXPECT_EQ(actual_remapped, match.remapped);
+ FileSpec remapped_spec(match.remapped.GetStringRef(), false);
+ FileSpec unmapped_spec;
+ EXPECT_TRUE(map.ReverseRemapPath(remapped_spec, unmapped_spec));
+ std::string unmapped_path = unmapped_spec.GetPath();
+ EXPECT_EQ(unmapped_path, orig_normalized);
+ }
+ }
+}
+
+TEST(PathMappingListTest, RelativeTests) {
+ Matches matches[] = {
+ {".", "/tmp"},
+ {"./", "/tmp"},
+ {"./////", "/tmp"},
+ {"./foo.c", "/tmp/foo.c"},
+ {"foo.c", "/tmp/foo.c"},
+ {"./bar/foo.c", "/tmp/bar/foo.c"},
+ {"bar/foo.c", "/tmp/bar/foo.c"},
+ };
+ ConstString fails[] = {
+ ConstString("/a"),
+ ConstString("/"),
+ };
+ PathMappingList map;
+ map.Append(ConstString("."), ConstString("/tmp"), false);
+ TestPathMappings(map, matches, fails);
+ PathMappingList map2;
+ map2.Append(ConstString(""), ConstString("/tmp"), false);
+ TestPathMappings(map, matches, fails);
+}
+
+TEST(PathMappingListTest, AbsoluteTests) {
+ PathMappingList map;
+ map.Append(ConstString("/old"), ConstString("/new"), false);
+ Matches matches[] = {
+ {"/old", "/new"},
+ {"/old/", "/new"},
+ {"/old/foo/.", "/new/foo"},
+ {"/old/foo.c", "/new/foo.c"},
+ {"/old/foo.c/.", "/new/foo.c"},
+ {"/old/./foo.c", "/new/foo.c"},
+ };
+ ConstString fails[] = {
+ ConstString("/foo"),
+ ConstString("/"),
+ ConstString("foo.c"),
+ ConstString("./foo.c"),
+ ConstString("../foo.c"),
+ ConstString("../bar/foo.c"),
+ };
+ TestPathMappings(map, matches, fails);
+}
+
+TEST(PathMappingListTest, RemapRoot) {
+ PathMappingList map;
+ map.Append(ConstString("/"), ConstString("/new"), false);
+ Matches matches[] = {
+ {"/old", "/new/old"},
+ {"/old/", "/new/old"},
+ {"/old/foo/.", "/new/old/foo"},
+ {"/old/foo.c", "/new/old/foo.c"},
+ {"/old/foo.c/.", "/new/old/foo.c"},
+ {"/old/./foo.c", "/new/old/foo.c"},
+ };
+ ConstString fails[] = {
+ ConstString("foo.c"),
+ ConstString("./foo.c"),
+ ConstString("../foo.c"),
+ ConstString("../bar/foo.c"),
+ };
+ TestPathMappings(map, matches, fails);
+}
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits