clayborg created this revision.
clayborg added reviewers: labath, zturner, davide.
Herald added subscribers: JDevlieghere, aprantl, mgorny.
PathMappingList was broken for relative and empty paths after normalization
changes in FileSpec. There were also no tests for PathMappingList so I added
those.
Changes include:
- Change PathMappingList::ReverseRemapPath() to take FileSpec objects instead
of ConstString. The only client of this was doing work to convert to and from
ConstString objects for no reason.
- Normalize all paths prefix and replacements that are added to the
PathMappingList vector so they match the paths that have been already
normalized in the debug info
- Unify code in the two forms of PathMappingList::RemapPath() so only one
contains the actual functionality. Prior to this, there were two versions of
this code.
- Use FileSpec::AppendPathComponent() and remove a long standing TODO so paths
are correctly appended to each other.
- Correctly handle the case where someone maps "" to something else. This
allows all paths to be prefixed with the replacement.
- Added tests for absolute, relative and empty paths.
https://reviews.llvm.org/D47021
Files:
include/lldb/Target/PathMappingList.h
lldb.xcodeproj/project.pbxproj
source/Target/PathMappingList.cpp
source/Target/Target.cpp
unittests/Utility/CMakeLists.txt
unittests/Utility/PathMappingListTest.cpp
Index: unittests/Utility/PathMappingListTest.cpp
===================================================================
--- unittests/Utility/PathMappingListTest.cpp
+++ unittests/Utility/PathMappingListTest.cpp
@@ -0,0 +1,101 @@
+//===-- NameMatchesTest.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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) {}
+ };
+}
+
+TEST(PathMappingListTest, RelativeTests) {
+ PathMappingList map;
+ map.Append(ConstString("."), ConstString("/tmp"), false);
+ Matches tests[] = {
+ {".", "/tmp"},
+ {"./", "/tmp"},
+ {"./////", "/tmp"},
+ {"./foo.c", "/tmp/foo.c"},
+ {"./bar/foo.c", "/tmp/bar/foo.c"}
+ };
+ ConstString actual_remapped;
+ EXPECT_FALSE(map.RemapPath(ConstString("/foo"), actual_remapped));
+ for (const auto &m: tests) {
+ FileSpec orig_spec(m.original.GetCString(), false);
+ std::string orig_normalized = orig_spec.GetPath();
+ EXPECT_TRUE(map.RemapPath(m.original, actual_remapped));
+ EXPECT_TRUE(actual_remapped == m.remapped);
+ FileSpec remapped_spec(m.remapped.GetCString(), false);
+ FileSpec unmapped_spec;
+ EXPECT_TRUE(map.ReverseRemapPath(remapped_spec, unmapped_spec));
+ std::string unmapped_path = unmapped_spec.GetPath();
+ EXPECT_TRUE(unmapped_path == orig_normalized);
+ }
+}
+
+TEST(PathMappingListTest, AbsoluteTests) {
+ PathMappingList map;
+ map.Append(ConstString("/old"), ConstString("/new"), false);
+ Matches tests[] = {
+ {"/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 actual_remapped;
+ // Make sure that the path
+ for (const auto &m: tests) {
+ FileSpec orig_spec(m.original.GetCString(), false);
+ std::string orig_normalized = orig_spec.GetPath();
+ EXPECT_TRUE(map.RemapPath(m.original, actual_remapped));
+ EXPECT_TRUE(actual_remapped == m.remapped);
+ FileSpec remapped_spec(m.remapped.GetCString(), false);
+ FileSpec unmapped_spec;
+ EXPECT_TRUE(map.ReverseRemapPath(remapped_spec, unmapped_spec));
+ std::string unmapped_path = unmapped_spec.GetPath();
+ EXPECT_TRUE(unmapped_path == orig_normalized);
+ }
+}
+
+TEST(PathMappingListTest, RemapEverything) {
+ PathMappingList map;
+ map.Append(ConstString(""), ConstString("/new"), false);
+ Matches tests[] = {
+ {"/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 actual_remapped;
+ // Make sure that the path
+ for (const auto &m: tests) {
+ FileSpec orig_spec(m.original.GetCString(), false);
+ std::string orig_normalized = orig_spec.GetPath();
+ EXPECT_TRUE(map.RemapPath(m.original, actual_remapped));
+ EXPECT_TRUE(actual_remapped == m.remapped);
+ FileSpec remapped_spec(m.remapped.GetCString(), false);
+ FileSpec unmapped_spec;
+ EXPECT_TRUE(map.ReverseRemapPath(remapped_spec, unmapped_spec));
+ std::string unmapped_path = unmapped_spec.GetPath();
+ EXPECT_TRUE(unmapped_path == orig_normalized);
+ }
+}
Index: unittests/Utility/CMakeLists.txt
===================================================================
--- unittests/Utility/CMakeLists.txt
+++ unittests/Utility/CMakeLists.txt
@@ -8,6 +8,7 @@
JSONTest.cpp
LogTest.cpp
NameMatchesTest.cpp
+ PathMappingListTest.cpp
StatusTest.cpp
StringExtractorTest.cpp
StructuredDataTest.cpp
Index: source/Target/Target.cpp
===================================================================
--- source/Target/Target.cpp
+++ 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: source/Target/PathMappingList.cpp
===================================================================
--- source/Target/PathMappingList.cpp
+++ 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,26 @@
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) {
+ // Don't change nothing into ".", nothing will remap all files to the
+ // other path
+ if (!path)
+ return 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.GetCString(), false).GetPath());
+ }
+}
//----------------------------------------------------------------------
// PathMappingList constructor
//----------------------------------------------------------------------
@@ -52,7 +73,7 @@
void PathMappingList::Append(const ConstString &path,
const ConstString &replacement, bool notify) {
++m_mod_id;
- m_pairs.push_back(pair(path, replacement));
+ m_pairs.push_back(pair(NormalizePath(path), NormalizePath(replacement)));
if (notify && m_callback)
m_callback(*this, m_callback_baton);
}
@@ -77,7 +98,8 @@
insert_iter = m_pairs.end();
else
insert_iter = m_pairs.begin() + index;
- m_pairs.insert(insert_iter, pair(path, replacement));
+ m_pairs.insert(insert_iter, pair(NormalizePath(path),
+ NormalizePath(replacement)));
if (notify && m_callback)
m_callback(*this, m_callback_baton);
}
@@ -88,7 +110,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,56 +156,48 @@
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.SetCStringWithLength(remapped.c_str(), remapped.size());
+ 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()))
+
+ for (const auto &it : m_pairs) {
+ auto prefix = it.first.GetStringRef();
+ if (!path.consume_front(prefix))
continue;
-
- new_path = pos->second.GetStringRef();
- new_path.append(path);
+ FileSpec remapped(it.second.GetStringRef(), false);
+ remapped.AppendPathComponent(path);
+ new_path = std::move(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.data(), path.size());
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());
+ llvm::StringRef second(it.second.GetCString(), it.second.GetLength());
+ if (path_ref.startswith(second)) {
+ llvm::StringRef first(it.first.GetCString(), it.first.GetLength());
+ llvm::StringRef suffix = path_ref.substr(second.size());
+ if (first.empty()) {
+ // If our original path was "", then the new path is just the suffix.
+ // If we call fixed.SetFile("", false) we will end up with "." as the
+ // path and any path we appended would end up being relative.
+ fixed.SetFile(suffix, false);
+ } else {
+ fixed.SetFile(first, false);
+ fixed.AppendPathComponent(suffix);
+ }
return true;
}
}
@@ -277,7 +291,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.xcodeproj/project.pbxproj
===================================================================
--- lldb.xcodeproj/project.pbxproj
+++ lldb.xcodeproj/project.pbxproj
@@ -211,6 +211,7 @@
264A58EE1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A58ED1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp */; };
264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */; };
264D8D5013661BD7003A368F /* UnwindAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */; };
+ 264FA56720A608F900134FA2 /* PathMappingListTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264FA56620A608F900134FA2 /* PathMappingListTest.cpp */; };
265192C61BA8E905002F08F6 /* CompilerDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265192C51BA8E905002F08F6 /* CompilerDecl.cpp */; };
265205A813D3E3F700132FE2 /* RegisterContextKDP_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */; };
265205AA13D3E3F700132FE2 /* RegisterContextKDP_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A413D3E3F700132FE2 /* RegisterContextKDP_i386.cpp */; };
@@ -1722,6 +1723,7 @@
264AD83911095BBD00E0B039 /* CommandObjectLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectLog.h; path = source/Commands/CommandObjectLog.h; sourceTree = "<group>"; };
264D8D4E13661BCC003A368F /* UnwindAssembly.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UnwindAssembly.h; path = include/lldb/Target/UnwindAssembly.h; sourceTree = "<group>"; };
264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindAssembly.cpp; path = source/Target/UnwindAssembly.cpp; sourceTree = "<group>"; };
+ 264FA56620A608F900134FA2 /* PathMappingListTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PathMappingListTest.cpp; sourceTree = "<group>"; };
265192C41BA8E8F8002F08F6 /* CompilerDecl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CompilerDecl.h; path = include/lldb/Symbol/CompilerDecl.h; sourceTree = "<group>"; };
265192C51BA8E905002F08F6 /* CompilerDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerDecl.cpp; path = source/Symbol/CompilerDecl.cpp; sourceTree = "<group>"; };
265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextKDP_arm.cpp; sourceTree = "<group>"; };
@@ -3473,6 +3475,7 @@
9A3D43C81F3150D200EB767C /* ConstStringTest.cpp */,
23CB14FD1D66CD2400EDDDE1 /* FileSpecTest.cpp */,
9A3D43C71F3150D200EB767C /* LogTest.cpp */,
+ 264FA56620A608F900134FA2 /* PathMappingListTest.cpp */,
9A3D43CB1F3150D200EB767C /* NameMatchesTest.cpp */,
9A3D43C61F3150D200EB767C /* StatusTest.cpp */,
9A3D43CA1F3150D200EB767C /* StructuredDataTest.cpp */,
@@ -7351,6 +7354,7 @@
23CB15341D66DA9300EDDDE1 /* CPlusPlusLanguageTest.cpp in Sources */,
9A2057381F3B8E7E00F6C293 /* FileSystemTest.cpp in Sources */,
9A2057201F3B8D2500F6C293 /* UnixSignalsTest.cpp in Sources */,
+ 264FA56720A608F900134FA2 /* PathMappingListTest.cpp in Sources */,
AFAFD80A1E57E1B90017A14F /* ModuleCacheTest.cpp in Sources */,
9A3D43DA1F3151C400EB767C /* StructuredDataTest.cpp in Sources */,
9A2057121F3B824B00F6C293 /* SymbolFileDWARFTests.cpp in Sources */,
Index: include/lldb/Target/PathMappingList.h
===================================================================
--- include/lldb/Target/PathMappingList.h
+++ 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.
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits