This patch adds a new "target.auto-source-map-relative" setting.
If enabled, this setting may auto deduce a source map entry based on requested
breakpoint path and the original path stored in debug info for resolved
breakpoint.
As an example, if debug info contains "./a/b/c/main.cpp", user sets a source
breakpoint at "/root/repo/x/y/z/a/b/c/main.cpp". The breakpoint will resolve
correctly now with Greg's patch https://reviews.llvm.org/D130401. However, the
resolved breakpoint will use "./a/b/c/main.cpp" to locate source file during
stop event which would fail most of the time.
With the new "target.auto-source-map-relative" setting enabled, a auto deduced
source map entry "." => "/root/repo/x/y/z" will be added. This new mapping will
help lldb to map resolved breakpoint path "./a/b/c/main.cpp" back to
"/root/repo/x/y/z/a/b/c/main.cpp" and locate it on disk.
If an existing source map entry is used the patch also concatenates the auto
deduced entry with any stripped reverse mapping prefix (see example below).
As a second example, debug info contains "./a/b/c/main.cpp" and user sets
breakpoint at "/root/repo/x/y/z/a/b/c/main.cpp". Let's say there is an existing
source map entry "." => "/root/repo"; this mapping would strip the prefix out of
"/root/repo/x/y/z/a/b/c/main.cpp" and use "x/y/z/a/b/c/main.cpp" to resolve
breakpoint. "target.auto-source-map-relative" setting would auto deduce a new
potential mapping of "." => "x/y/z", then it detects that there is a stripped
prefix from reverse mapping and concatenates it as the new mapping:
"." => "/root/repo/x/y/z" which would correct map "./a/b/c/main.cpp" path to
new path in disk.
This patches depends on https://reviews.llvm.org/D130401 to use new added
SBDebugger::GetSetting() API for testing.
Differential Revision: https://reviews.llvm.org/D133042
141 lines
4.2 KiB
C++
141 lines
4.2 KiB
C++
//===-- PathMappingListTest.cpp -------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Target/PathMappingList.h"
|
|
#include "lldb/Utility/FileSpec.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "gtest/gtest.h"
|
|
#include <utility>
|
|
|
|
using namespace lldb_private;
|
|
|
|
namespace {
|
|
struct Matches {
|
|
FileSpec original;
|
|
FileSpec remapped;
|
|
Matches(const char *o, const char *r) : original(o), remapped(r) {}
|
|
Matches(const char *o, llvm::sys::path::Style style, const char *r)
|
|
: original(o, style), remapped(r) {}
|
|
};
|
|
} // namespace
|
|
|
|
static void TestPathMappings(const PathMappingList &map,
|
|
llvm::ArrayRef<Matches> matches,
|
|
llvm::ArrayRef<ConstString> fails) {
|
|
ConstString actual_remapped;
|
|
for (const auto &fail : fails) {
|
|
SCOPED_TRACE(fail.GetCString());
|
|
EXPECT_FALSE(map.RemapPath(fail, actual_remapped))
|
|
<< "actual_remapped: " << actual_remapped.GetCString();
|
|
}
|
|
for (const auto &match : matches) {
|
|
SCOPED_TRACE(match.original.GetPath() + " -> " + match.remapped.GetPath());
|
|
std::string orig_normalized = match.original.GetPath();
|
|
EXPECT_TRUE(
|
|
map.RemapPath(ConstString(match.original.GetPath()), actual_remapped));
|
|
EXPECT_EQ(FileSpec(actual_remapped.GetStringRef()), match.remapped);
|
|
FileSpec unmapped_spec;
|
|
EXPECT_TRUE(map.ReverseRemapPath(match.remapped, unmapped_spec).hasValue());
|
|
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[] = {
|
|
#ifdef _WIN32
|
|
ConstString("C:\\"),
|
|
ConstString("C:\\a"),
|
|
#else
|
|
ConstString("/a"),
|
|
ConstString("/"),
|
|
#endif
|
|
};
|
|
PathMappingList map;
|
|
map.Append(".", "/tmp", false);
|
|
TestPathMappings(map, matches, fails);
|
|
PathMappingList map2;
|
|
map2.Append("", "/tmp", false);
|
|
TestPathMappings(map, matches, fails);
|
|
}
|
|
|
|
TEST(PathMappingListTest, AbsoluteTests) {
|
|
PathMappingList map;
|
|
map.Append("/old", "/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("/", "/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);
|
|
}
|
|
|
|
#ifndef _WIN32
|
|
TEST(PathMappingListTest, CrossPlatformTests) {
|
|
PathMappingList map;
|
|
map.Append(R"(C:\old)", "/new", false);
|
|
Matches matches[] = {
|
|
{R"(C:\old)", llvm::sys::path::Style::windows, "/new"},
|
|
{R"(C:\old\)", llvm::sys::path::Style::windows, "/new"},
|
|
{R"(C:\old\foo\.)", llvm::sys::path::Style::windows, "/new/foo"},
|
|
{R"(C:\old\foo.c)", llvm::sys::path::Style::windows, "/new/foo.c"},
|
|
{R"(C:\old\foo.c\.)", llvm::sys::path::Style::windows, "/new/foo.c"},
|
|
{R"(C:\old\.\foo.c)", llvm::sys::path::Style::windows, "/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);
|
|
}
|
|
#endif
|