[Lldb-commits] [lldb] Realpath symlinks for breakpoints (PR #102223)
via lldb-commits
lldb-commits at lists.llvm.org
Tue Aug 6 13:59:13 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: None (royitaqi)
<details>
<summary>Changes</summary>
# TL;DR
Improve the chance of resolving file/line breakpoints by, as a second matching attempt, realpath'ing the support files who has a matching basename and whose path matches one of the prefixes in a setting.
Telemetries and tests are included.
# Problem
In some development environment, some source files are symlinked for some reasons, then the symlink files are used in the build. This causes the debug info to contain the path to the symlink files, not the original source files. However, during debugging, the IDE opens and uses the original source file to set breakpoints. The result is a mismatch between the source file's real path v.s. the symlink's path, causing file/line breakpoints to be unresolved for these files.
# Feature
After the normal file/path matching attempt fails, if the basename of the files match yet the directories don't AND the support file's path matches of the prefixes in the setting (see below), realpath the support file, then reattempt the match.
# Setting
A list of prefixes, which the support file's path has to match in order to be realpath'ed. The default is an empty list, which will cost nothing.
# Telemetries
are added. They can be obtained as a part of the Target's Statistics (e.g. `statistics dump`).
1. The number of realpath attempts made.
2. The number of times such realpath'ing help found a match.
# Tests
are added:
```
ninja lldb-unit-test-deps
tools/lldb/unittests/Utility/UtilityTests --gtest_filter="SupportFileList*"
tools/lldb/unittests/Utility/UtilityTests --gtest_filter="RealpathPrefixes*"
```
---
Patch is 36.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/102223.diff
18 Files Affected:
- (modified) lldb/include/lldb/Symbol/CompileUnit.h (+11-3)
- (modified) lldb/include/lldb/Target/Statistics.h (+4)
- (modified) lldb/include/lldb/Target/Target.h (+3)
- (modified) lldb/include/lldb/Utility/FileSpecList.h (+8-1)
- (added) lldb/include/lldb/Utility/RealpathPrefixes.h (+63)
- (modified) lldb/source/Breakpoint/BreakpointResolverFileLine.cpp (+5-1)
- (modified) lldb/source/Symbol/CompileUnit.cpp (+8-6)
- (modified) lldb/source/Target/Statistics.cpp (+12)
- (modified) lldb/source/Target/Target.cpp (+10)
- (modified) lldb/source/Target/TargetProperties.td (+3)
- (modified) lldb/source/Utility/CMakeLists.txt (+1)
- (modified) lldb/source/Utility/FileSpecList.cpp (+73-35)
- (added) lldb/source/Utility/RealpathPrefixes.cpp (+66)
- (modified) lldb/unittests/Core/CMakeLists.txt (-1)
- (modified) lldb/unittests/Utility/CMakeLists.txt (+3)
- (renamed) lldb/unittests/Utility/FileSpecListTest.cpp (+130)
- (added) lldb/unittests/Utility/MockSymlinkFileSystem.h (+66)
- (added) lldb/unittests/Utility/RealpathPrefixesTest.cpp (+147)
``````````diff
diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index c20a37e3283075..c8ce99b01b62f3 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -24,6 +24,8 @@
#include "llvm/ADT/DenseSet.h"
namespace lldb_private {
+class RealpathPrefixes;
+
/// \class CompileUnit CompileUnit.h "lldb/Symbol/CompileUnit.h"
/// A class that describes a compilation unit.
///
@@ -389,10 +391,16 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
/// A SymbolContext list class that will get any matching
/// entries appended to.
///
+ /// \param[in] realpath_prefixes
+ /// Paths that start with one of the prefixes in this list will be
+ /// realpath'ed to resolve any symlinks.
+ ///
/// \see enum SymbolContext::Scope
- void ResolveSymbolContext(const SourceLocationSpec &src_location_spec,
- lldb::SymbolContextItem resolve_scope,
- SymbolContextList &sc_list);
+ void
+ ResolveSymbolContext(const SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ SymbolContextList &sc_list,
+ const RealpathPrefixes *realpath_prefixes = nullptr);
/// Get whether compiler optimizations were enabled for this compile unit
///
diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h
index 35bd7f8a66e055..2ce56309aefc39 100644
--- a/lldb/include/lldb/Target/Statistics.h
+++ b/lldb/include/lldb/Target/Statistics.h
@@ -184,6 +184,8 @@ class TargetStats {
void SetFirstPrivateStopTime();
void SetFirstPublicStopTime();
void IncreaseSourceMapDeduceCount();
+ void IncreaseSourceRealpathAttemptCount();
+ void IncreaseSourceRealpathCompatibleCount();
StatsDuration &GetCreateTime() { return m_create_time; }
StatsSuccessFail &GetExpressionStats() { return m_expr_eval; }
@@ -198,6 +200,8 @@ class TargetStats {
StatsSuccessFail m_frame_var{"frameVariable"};
std::vector<intptr_t> m_module_identifiers;
uint32_t m_source_map_deduce_count = 0;
+ uint32_t m_source_realpath_attempt_count = 0;
+ uint32_t m_source_realpath_compatible_count = 0;
void CollectStats(Target &target);
};
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 119dff4d498199..7f4d607f5427df 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -34,6 +34,7 @@
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/RealpathPrefixes.h"
#include "lldb/Utility/Timeout.h"
#include "lldb/lldb-public.h"
@@ -117,6 +118,8 @@ class TargetProperties : public Properties {
InlineStrategy GetInlineStrategy() const;
+ RealpathPrefixes GetSourceRealpathPrefixes() const;
+
llvm::StringRef GetArg0() const;
void SetArg0(llvm::StringRef arg);
diff --git a/lldb/include/lldb/Utility/FileSpecList.h b/lldb/include/lldb/Utility/FileSpecList.h
index 6eb3bb9971f13a..99a99a45a1dad2 100644
--- a/lldb/include/lldb/Utility/FileSpecList.h
+++ b/lldb/include/lldb/Utility/FileSpecList.h
@@ -17,6 +17,7 @@
#include <vector>
namespace lldb_private {
+class RealpathPrefixes;
class Stream;
/// A list of support files for a CompileUnit.
@@ -64,10 +65,16 @@ class SupportFileList {
/// \param[in] file
/// The file specification to search for.
///
+ /// \param[in] realpath_prefixes
+ /// Paths that start with one of the prefixes in this list will be
+ /// realpath'ed to resolve any symlinks.
+ ///
/// \return
/// The index of the file that matches \a file if it is found,
/// else UINT32_MAX is returned.
- size_t FindCompatibleIndex(size_t idx, const FileSpec &file) const;
+ size_t FindCompatibleIndex(
+ size_t idx, const FileSpec &file,
+ const RealpathPrefixes *realpath_prefixes = nullptr) const;
template <class... Args> void EmplaceBack(Args &&...args) {
m_files.push_back(
diff --git a/lldb/include/lldb/Utility/RealpathPrefixes.h b/lldb/include/lldb/Utility/RealpathPrefixes.h
new file mode 100644
index 00000000000000..b9387ec0dee731
--- /dev/null
+++ b/lldb/include/lldb/Utility/RealpathPrefixes.h
@@ -0,0 +1,63 @@
+//===-- RealpathPrefixes.h --------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_CORE_REALPATHPREFIXES_H
+#define LLDB_CORE_REALPATHPREFIXES_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace lldb_private {
+class FileSpec;
+class FileSpecList;
+class Target;
+} // namespace lldb_private
+
+namespace lldb_private {
+
+class RealpathPrefixes {
+public:
+ // Prefixes are obtained from FileSpecList, through FileSpec::GetPath(), which
+ // ensures that the paths are normalized. For example:
+ // "./foo/.." -> ""
+ // "./foo/../bar" -> "bar"
+ explicit RealpathPrefixes(const FileSpecList &file_spec_list);
+
+ // Sets an optional filesystem to use for realpath'ing. If not set, the real
+ // filesystem will be used.
+ void SetFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs);
+
+ // Sets an optional Target instance to gather statistics.
+ void SetTarget(Target *target) { m_target = target; }
+ Target *GetTarget() const { return m_target; }
+
+ std::optional<FileSpec> ResolveSymlinks(const FileSpec &file_spec) const;
+
+private:
+ // Paths that start with one of the prefixes in this list will be realpath'ed
+ // to resolve any symlinks.
+ //
+ // Wildcard prefixes:
+ // - "" (empty string) will match all paths.
+ // - "/" will match all absolute paths.
+ std::vector<std::string> m_prefixes;
+
+ // The filesystem to use for realpath'ing.
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs;
+
+ // The optional Target instance to gather statistics.
+ Target *m_target;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_CORE_REALPATHPREFIXES_H
diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
index 16c4ee1b88d162..315e017350d80b 100644
--- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp
@@ -15,6 +15,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RealpathPrefixes.h"
#include "lldb/Utility/StreamString.h"
#include <optional>
@@ -290,13 +291,16 @@ Searcher::CallbackReturn BreakpointResolverFileLine::SearchCallback(
const uint32_t line = m_location_spec.GetLine().value_or(0);
const std::optional<uint16_t> column = m_location_spec.GetColumn();
+ RealpathPrefixes realpath_prefixes =
+ GetBreakpoint()->GetTarget().GetSourceRealpathPrefixes();
+
const size_t num_comp_units = context.module_sp->GetNumCompileUnits();
for (size_t i = 0; i < num_comp_units; i++) {
CompUnitSP cu_sp(context.module_sp->GetCompileUnitAtIndex(i));
if (cu_sp) {
if (filter.CompUnitPasses(*cu_sp))
cu_sp->ResolveSymbolContext(m_location_spec, eSymbolContextEverything,
- sc_list);
+ sc_list, &realpath_prefixes);
}
}
diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp
index ddeacf18e855ee..f60745cb2e38e4 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -213,11 +213,12 @@ VariableListSP CompileUnit::GetVariableList(bool can_create) {
return m_variables;
}
-std::vector<uint32_t> FindFileIndexes(const SupportFileList &files,
- const FileSpec &file) {
+std::vector<uint32_t>
+FindFileIndexes(const SupportFileList &files, const FileSpec &file,
+ const RealpathPrefixes *realpath_prefixes = nullptr) {
std::vector<uint32_t> result;
uint32_t idx = -1;
- while ((idx = files.FindCompatibleIndex(idx + 1, file)) !=
+ while ((idx = files.FindCompatibleIndex(idx + 1, file, realpath_prefixes)) !=
UINT32_MAX)
result.push_back(idx);
return result;
@@ -247,7 +248,8 @@ uint32_t CompileUnit::FindLineEntry(uint32_t start_idx, uint32_t line,
void CompileUnit::ResolveSymbolContext(
const SourceLocationSpec &src_location_spec,
- SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
+ SymbolContextItem resolve_scope, SymbolContextList &sc_list,
+ const RealpathPrefixes *realpath_prefixes) {
const FileSpec file_spec = src_location_spec.GetFileSpec();
const uint32_t line = src_location_spec.GetLine().value_or(0);
const bool check_inlines = src_location_spec.GetCheckInlines();
@@ -275,8 +277,8 @@ void CompileUnit::ResolveSymbolContext(
return;
}
- std::vector<uint32_t> file_indexes = FindFileIndexes(GetSupportFiles(),
- file_spec);
+ std::vector<uint32_t> file_indexes =
+ FindFileIndexes(GetSupportFiles(), file_spec, realpath_prefixes);
const size_t num_file_indexes = file_indexes.size();
if (num_file_indexes == 0)
return;
diff --git a/lldb/source/Target/Statistics.cpp b/lldb/source/Target/Statistics.cpp
index 583d1524881fc3..894c247571ff90 100644
--- a/lldb/source/Target/Statistics.cpp
+++ b/lldb/source/Target/Statistics.cpp
@@ -192,6 +192,10 @@ TargetStats::ToJSON(Target &target,
}
target_metrics_json.try_emplace("sourceMapDeduceCount",
m_source_map_deduce_count);
+ target_metrics_json.try_emplace("sourceRealpathAttemptCount",
+ m_source_realpath_attempt_count);
+ target_metrics_json.try_emplace("sourceRealpathCompatibleCount",
+ m_source_realpath_compatible_count);
return target_metrics_json;
}
@@ -220,6 +224,14 @@ void TargetStats::IncreaseSourceMapDeduceCount() {
++m_source_map_deduce_count;
}
+void TargetStats::IncreaseSourceRealpathAttemptCount() {
+ ++m_source_realpath_attempt_count;
+}
+
+void TargetStats::IncreaseSourceRealpathCompatibleCount() {
+ ++m_source_realpath_compatible_count;
+}
+
bool DebuggerStats::g_collecting_stats = false;
llvm::json::Value DebuggerStats::ReportStatistics(
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 129683c43f0c1a..48feb97db6d083 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -60,6 +60,7 @@
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RealpathPrefixes.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
@@ -4354,6 +4355,15 @@ InlineStrategy TargetProperties::GetInlineStrategy() const {
static_cast<InlineStrategy>(g_target_properties[idx].default_uint_value));
}
+// Returning RealpathPrefixes, but the setting's type is FileSpecList. We do
+// this because we want the FileSpecList to normalize the file paths for us.
+RealpathPrefixes TargetProperties::GetSourceRealpathPrefixes() const {
+ const uint32_t idx = ePropertySourceRealpathPrefixes;
+ auto prefixes = RealpathPrefixes(GetPropertyAtIndexAs<FileSpecList>(idx, {}));
+ prefixes.SetTarget(this->m_target);
+ return prefixes;
+}
+
llvm::StringRef TargetProperties::GetArg0() const {
const uint32_t idx = ePropertyArg0;
return GetPropertyAtIndexAs<llvm::StringRef>(
diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index ef538678670fea..d037293c5a09f4 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -150,6 +150,9 @@ let Definition = "target" in {
DefaultEnumValue<"eInlineBreakpointsAlways">,
EnumValues<"OptionEnumValues(g_inline_breakpoint_enums)">,
Desc<"The strategy to use when settings breakpoints by file and line. Breakpoint locations can end up being inlined by the compiler, so that a compile unit 'a.c' might contain an inlined function from another source file. Usually this is limited to breakpoint locations from inlined functions from header or other include files, or more accurately non-implementation source files. Sometimes code might #include implementation files and cause inlined breakpoint locations in inlined implementation files. Always checking for inlined breakpoint locations can be expensive (memory and time), so if you have a project with many headers and find that setting breakpoints is slow, then you can change this setting to headers. This setting allows you to control exactly which strategy is used when setting file and line breakpoints.">;
+ def SourceRealpathPrefixes: Property<"source-realpath-prefixes", "FileSpecList">,
+ DefaultStringValue<"">,
+ Desc<"Realpath any source paths that start with one of these prefixes. If the debug info contains symlinks that don't match the original source file locations that the user will use to set breakpoints, then this setting can help resolve breakpoints correctly.">;
def DisassemblyFlavor: Property<"x86-disassembly-flavor", "Enum">,
DefaultEnumValue<"eX86DisFlavorDefault">,
EnumValues<"OptionEnumValues(g_x86_dis_flavor_value_types)">,
diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt
index e9954d66cd1a52..397db0e8976023 100644
--- a/lldb/source/Utility/CMakeLists.txt
+++ b/lldb/source/Utility/CMakeLists.txt
@@ -51,6 +51,7 @@ add_lldb_library(lldbUtility NO_INTERNAL_DEPENDENCIES
Log.cpp
NameMatches.cpp
ProcessInfo.cpp
+ RealpathPrefixes.cpp
RegisterValue.cpp
RegularExpression.cpp
Instrumentation.cpp
diff --git a/lldb/source/Utility/FileSpecList.cpp b/lldb/source/Utility/FileSpecList.cpp
index 7647e04a820451..d16789d65e8017 100644
--- a/lldb/source/Utility/FileSpecList.cpp
+++ b/lldb/source/Utility/FileSpecList.cpp
@@ -7,7 +7,12 @@
//===----------------------------------------------------------------------===//
#include "lldb/Utility/FileSpecList.h"
+#include "lldb/Target/Statistics.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RealpathPrefixes.h"
#include "lldb/Utility/Stream.h"
#include <cstdint>
@@ -108,52 +113,85 @@ size_t SupportFileList::FindFileIndex(size_t start_idx,
});
}
-size_t SupportFileList::FindCompatibleIndex(size_t start_idx,
- const FileSpec &file_spec) const {
- const size_t num_files = m_files.size();
- if (start_idx >= num_files)
- return UINT32_MAX;
+enum IsCompatibleResult {
+ kNoMatch = 0,
+ kOnlyFileMatch = 1,
+ kCompatible = 2,
+};
+IsCompatibleResult IsCompatible(const FileSpec &curr_file,
+ const FileSpec &file_spec) {
const bool file_spec_relative = file_spec.IsRelative();
const bool file_spec_case_sensitive = file_spec.IsCaseSensitive();
// When looking for files, we will compare only the filename if the directory
// argument is empty in file_spec
const bool full = !file_spec.GetDirectory().IsEmpty();
+ // Always start by matching the filename first
+ if (!curr_file.FileEquals(file_spec))
+ return IsCompatibleResult::kNoMatch;
+
+ // Only compare the full name if the we were asked to and if the current
+ // file entry has the a directory. If it doesn't have a directory then we
+ // only compare the filename.
+ if (FileSpec::Equal(curr_file, file_spec, full)) {
+ return IsCompatibleResult::kCompatible;
+ } else if (curr_file.IsRelative() || file_spec_relative) {
+ llvm::StringRef curr_file_dir = curr_file.GetDirectory().GetStringRef();
+ if (curr_file_dir.empty())
+ return IsCompatibleResult::kCompatible; // Basename match only for this
+ // file in the list
+
+ // Check if we have a relative path in our file list, or if "file_spec" is
+ // relative, if so, check if either ends with the other.
+ llvm::StringRef file_spec_dir = file_spec.GetDirectory().GetStringRef();
+ // We have a relative path in our file list, it matches if the
+ // specified path ends with this path, but we must ensure the full
+ // component matches (we don't want "foo/bar.cpp" to match "oo/bar.cpp").
+ auto is_suffix = [](llvm::StringRef a, llvm::StringRef b,
+ bool case_sensitive) -> bool {
+ if (case_sensitive ? a.consume_back(b) : a.consume_back_insensitive(b))
+ return a.empty() || a.ends_with("/");
+ return false;
+ };
+ const bool case_sensitive =
+ file_spec_case_sensitive || curr_file.IsCaseSensitive();
+ if (is_suffix(curr_file_dir, file_spec_dir, case_sensitive) ||
+ is_suffix(file_spec_dir, curr_file_dir, case_sensitive))
+ return IsCompatibleResult::kCompatible;
+ }
+ return IsCompatibleResult::kOnlyFileMatch;
+}
+
+size_t SupportFileList::FindCompatibleIndex(
+ size_t start_idx, const FileSpec &file_spec,
+ const RealpathPrefixes *realpath_prefixes) const {
+ const size_t num_files = m_files.size();
+ if (start_idx >= num_files)
+ return UINT32_MAX;
+
for (size_t idx = start_idx; idx < num_files; ++idx) {
const FileSpec &curr_file = m_files[idx]->GetSpecOnly();
- // Always start by matching the filename first
- if (!curr_file.FileEquals(file_spec))
- continue;
-
- // Only compare the full name if the we were asked to and if the current
- // file entry has the a directory. If it doesn't have a directory then we
- // only compare the filename.
- if (FileSpec::Equal(curr_file, file_spec, full)) {
+ IsCompatibleResult result = IsCompatible(curr_file, file_spec);
+ if (result == IsCompatibleResult::kCompatible)
return idx;
- } else if (curr_file.IsRelative() || file_spec_relative) {
- llvm::StringRef curr_file_dir = curr_file.GetDirectory().GetStringRef();
- if (curr_file_dir.empty())
- return idx; // Basename match only for this file in the list
-
- // Check if we have a relative path in our file list, or if "file_spec" is
- // relative, if so, check if either ends with the other.
- llvm::StringRef file_spec_dir = file_spec.GetDirectory().GetStringRef();
- // We have a relative path in our file list, it matches if the
- // specified path ends with this path, but we must ensure the full
- // component matches (we don't want "foo/bar.cpp" to match "oo/bar.cpp").
- auto is_suffix = [](llvm::StringRef a, llvm::StringRef b,
- bool case_sensitive) -> bool {
- if (case_sensitive ? a.consume_back(b) : a.consume_back_insensitive(b))
- return a.empty() || a.ends_with("/");
- return false;
- };
- const bool case_sensitive =
- file_spec_case_sensitive || curr_file.IsCaseSensitive();
- if (is_suffix(curr_file_dir, file_spec_dir, case_sensitive) ||
- is_suffix(file_spec_dir, curr_file_dir, case_sensitive))
- return idx;
+
+ if (realpath_prefixes && result == IsCompatibleResult::kOnlyFileMatch) {
+ if (std::optional<FileSpec> resolved_curr_file =
+ realpath_prefixes->ResolveSymlinks(curr_file)) {
+ if (IsCompatible(*resolved_curr_file, file_spec)) {
+ // Stats and logging.
+ if (Target *target = realpath_prefixes->GetTarget())
+ target->GetStatistics().IncreaseSourceRealpathCompatibleCount();
+ Log *log = GetLog(LLDBLog::Source);
+ LLDB_LOGF(log,
+ "Realpath'ed support file %s is compatible to input file",
+ resolved_curr_file->GetPath().c_str());
+ // We found a match
+ return idx;
+ }
+ }
}
}
diff --git a/lldb/source/Utility/RealpathPrefixes.cpp b/lldb/source/Utility/RealpathPrefixes.cpp
new file mode 100644
index 00000000000000..646f08ef409c44
--- /dev/null
+++ b/lldb/source/...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/102223
More information about the lldb-commits
mailing list