[Lldb-commits] [lldb] [lldb][ResolveSourceFileCallback] Call resolve source file callback (PR #120833)

via lldb-commits lldb-commits at lists.llvm.org
Sat Dec 21 01:13:56 PST 2024


https://github.com/rchamala updated https://github.com/llvm/llvm-project/pull/120833

>From d8f99abee76a3d74d6c5c4904304f77cb2142087 Mon Sep 17 00:00:00 2001
From: Rahul Reddy Chamala <rachamal at fb.com>
Date: Thu, 19 Dec 2024 20:56:21 -0800
Subject: [PATCH] [lldb][ResolveSourceFileCallback] Call resolve source file
 callback

Summary:
RFC https://discourse.llvm.org/t/rfc-python-callback-for-source-file-resolution/83545

Updated LineEntry::ApplyFileMappings to call resolve source file callback if set.

include/lldb/Target/Platform.h, source/Target/Platform.cpp
Implemented SetResolveSourceFileCallback and GetResolveSourceFileCallback

include/lldb/Symbol/LineEntry.h, Source/Symbol/LineEntry.cpp
Implemented CallResolveSourceFileCallbackIfSet

Source/Target/StackFrame.cpp
Source/Target/StackFrameList.cpp
Source/Target/ThreadPlanStepRange.cpp
Updated the caller  to ApplyFileMappings


unittests/Symbol/TestLineEntry.cpp
Added comprehensive ResolveSourceFileCallback tests.

Test Plan:
Added unittests for LineEntry.

```
ninja check-lldb-unit
```
---
 lldb/include/lldb/Symbol/LineEntry.h          |   5 +-
 lldb/include/lldb/Target/Platform.h           |  19 ++
 lldb/source/Symbol/LineEntry.cpp              |  37 +++-
 lldb/source/Target/Platform.cpp               |  55 ++++++
 lldb/source/Target/StackFrame.cpp             |   2 +-
 lldb/source/Target/StackFrameList.cpp         |   3 +-
 lldb/source/Target/ThreadPlanStepRange.cpp    |   7 +-
 lldb/unittests/Symbol/CMakeLists.txt          |   2 +
 .../Symbol/Inputs/inlined-functions.cpp       |  22 +++
 lldb/unittests/Symbol/TestLineEntry.cpp       | 164 +++++++++++++++++-
 10 files changed, 302 insertions(+), 14 deletions(-)
 create mode 100644 lldb/unittests/Symbol/Inputs/inlined-functions.cpp

diff --git a/lldb/include/lldb/Symbol/LineEntry.h b/lldb/include/lldb/Symbol/LineEntry.h
index 8da59cf0bd24aa..9fc334ed87fdab 100644
--- a/lldb/include/lldb/Symbol/LineEntry.h
+++ b/lldb/include/lldb/Symbol/LineEntry.h
@@ -128,7 +128,10 @@ struct LineEntry {
   ///
   /// \param[in] target_sp
   ///     Shared pointer to the target this LineEntry belongs to.
-  void ApplyFileMappings(lldb::TargetSP target_sp);
+  ///
+  /// \param[in] module_sp
+  ///     Shared pointer to the module this LineEntry belongs to.
+  void ApplyFileMappings(lldb::TargetSP target_sp, lldb::ModuleSP module_sp);
 
   /// Helper to access the file.
   const FileSpec &GetFile() const { return file_sp->GetSpecOnly(); }
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index a702abb540fd93..3265d0d2145dd6 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -316,6 +316,12 @@ class Platform : public PluginInterface {
   virtual bool GetModuleSpec(const FileSpec &module_file_spec,
                              const ArchSpec &arch, ModuleSpec &module_spec);
 
+  void
+  CallResolveSourceFileCallbackIfSet(const lldb::ModuleSP &module_sp,
+                                     const FileSpec &original_source_file_spec,
+                                     FileSpec &resolved_source_file_spec,
+                                     bool *did_create_ptr);
+
   virtual Status ConnectRemote(Args &args);
 
   virtual Status DisconnectRemote();
@@ -967,6 +973,11 @@ class Platform : public PluginInterface {
                                FileSpec &symbol_file_spec)>
       LocateModuleCallback;
 
+  typedef std::function<Status(const lldb::ModuleSP &module_sp,
+                               const FileSpec &original_file_spec,
+                               FileSpec &resolved_file_spec)>
+      ResolveSourceFileCallback;
+
   /// Set locate module callback. This allows users to implement their own
   /// module cache system. For example, to leverage artifacts of build system,
   /// to bypass pulling files from remote platform, or to search symbol files
@@ -975,6 +986,13 @@ class Platform : public PluginInterface {
 
   LocateModuleCallback GetLocateModuleCallback() const;
 
+  /// Set resolve source file callback. This allows users to implement their own
+  /// source file cache system. For example, to search source files from source
+  /// servers.
+  void SetResolveSourceFileCallback(ResolveSourceFileCallback callback);
+
+  ResolveSourceFileCallback GetResolveSourceFileCallback() const;
+
 protected:
   /// Create a list of ArchSpecs with the given OS and a architectures. The
   /// vendor field is left as an "unspecified unknown".
@@ -1022,6 +1040,7 @@ class Platform : public PluginInterface {
   bool m_calculated_trap_handlers;
   const std::unique_ptr<ModuleCache> m_module_cache;
   LocateModuleCallback m_locate_module_callback;
+  ResolveSourceFileCallback m_resolve_source_file_callback;
 
   /// Ask the Platform subclass to fill in the list of trap handler names
   ///
diff --git a/lldb/source/Symbol/LineEntry.cpp b/lldb/source/Symbol/LineEntry.cpp
index c941a6927cb93f..1a966cc1c8387d 100644
--- a/lldb/source/Symbol/LineEntry.cpp
+++ b/lldb/source/Symbol/LineEntry.cpp
@@ -7,7 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Symbol/LineEntry.h"
+#include "lldb/Core/Module.h"
 #include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Platform.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 
@@ -241,13 +244,33 @@ AddressRange LineEntry::GetSameLineContiguousAddressRange(
   return complete_line_range;
 }
 
-void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) {
-  if (target_sp) {
-    // Apply any file remappings to our file.
-    if (auto new_file_spec = target_sp->GetSourcePathMap().FindFile(
-            original_file_sp->GetSpecOnly())) {
-      file_sp = std::make_shared<SupportFile>(*new_file_spec,
-                                              original_file_sp->GetChecksum());
+void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp,
+                                  lldb::ModuleSP module_sp) {
+  if (!target_sp) {
+    return;
+  }
+
+  // Apply any file remappings to our file.
+  if (auto new_file_spec = target_sp->GetSourcePathMap().FindFile(
+          original_file_sp->GetSpecOnly())) {
+    file_sp = std::make_shared<SupportFile>(*new_file_spec,
+                                            original_file_sp->GetChecksum());
+  }
+
+  lldb::PlatformSP platform_sp = target_sp->GetPlatform();
+  if (module_sp && platform_sp) {
+    FileSpec original_file_spec = original_file_sp->GetSpecOnly();
+    FileSpec resolved_source_file_spec;
+    bool didResolveSourceFile = false;
+
+    // Call resolve source file callback if set. This allows users to implement
+    // their own source file cache system. For example, to search source files
+    // from source servers.
+    platform_sp->CallResolveSourceFileCallbackIfSet(
+        module_sp, original_file_spec, resolved_source_file_spec,
+        &didResolveSourceFile);
+    if (didResolveSourceFile) {
+      file_sp = std::make_shared<SupportFile>(resolved_source_file_spec);
     }
   }
 }
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index 3e7546048e5862..9f56888693fc42 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -1696,6 +1696,51 @@ void Platform::CallLocateModuleCallbackIfSet(const ModuleSpec &module_spec,
   }
 }
 
+void Platform::CallResolveSourceFileCallbackIfSet(
+    const lldb::ModuleSP &module_sp, const FileSpec &original_source_file_spec,
+    FileSpec &resolved_source_file_spec, bool *did_create_ptr) {
+  if (!m_resolve_source_file_callback) {
+    // Resolve source file callback is not set.
+    return;
+  }
+
+  Status error = m_resolve_source_file_callback(
+      module_sp, original_source_file_spec, resolved_source_file_spec);
+
+  // Resolve source file callback is set and called. Check the error.
+  Log *log = GetLog(LLDBLog::Platform);
+  if (error.Fail()) {
+    LLDB_LOGF(log, "%s: Resolve source file callback failed: %s",
+              LLVM_PRETTY_FUNCTION, error.AsCString());
+    return;
+  }
+
+  if (!resolved_source_file_spec) {
+    LLDB_LOGF(log,
+              "%s: Resolve source file callback did not set "
+              "resolved_source_file_spec",
+              LLVM_PRETTY_FUNCTION);
+    return;
+  }
+
+  // If the callback returned a source file, it should exist.
+  if (resolved_source_file_spec &&
+      !FileSystem::Instance().Exists(resolved_source_file_spec)) {
+    LLDB_LOGF(log,
+              "%s: Resolve source file callback set a non-existent file to "
+              "source_file_spec: %s",
+              LLVM_PRETTY_FUNCTION,
+              resolved_source_file_spec.GetPath().c_str());
+    // Clear source_file_spec for the error.
+    resolved_source_file_spec.Clear();
+    return;
+  }
+
+  if (did_create_ptr) {
+    *did_create_ptr = true;
+  }
+}
+
 bool Platform::GetCachedSharedModule(const ModuleSpec &module_spec,
                                      lldb::ModuleSP &module_sp,
                                      bool *did_create_ptr) {
@@ -2104,6 +2149,16 @@ Platform::LocateModuleCallback Platform::GetLocateModuleCallback() const {
   return m_locate_module_callback;
 }
 
+void Platform::SetResolveSourceFileCallback(
+    ResolveSourceFileCallback callback) {
+  m_resolve_source_file_callback = callback;
+}
+
+Platform::ResolveSourceFileCallback
+Platform::GetResolveSourceFileCallback() const {
+  return m_resolve_source_file_callback;
+}
+
 PlatformSP PlatformList::GetOrCreate(llvm::StringRef name) {
   std::lock_guard<std::recursive_mutex> guard(m_mutex);
   for (const PlatformSP &platform_sp : m_platforms) {
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 2633c976c13bf4..404d93e75642f4 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -396,7 +396,7 @@ StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {
         if ((resolved & eSymbolContextLineEntry) &&
             !m_sc.line_entry.IsValid()) {
           m_sc.line_entry = sc.line_entry;
-          m_sc.line_entry.ApplyFileMappings(m_sc.target_sp);
+          m_sc.line_entry.ApplyFileMappings(m_sc.target_sp, m_sc.module_sp);
         }
       }
     } else {
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index 9c6208e9e0a65a..d7211da1ef94e0 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -494,7 +494,8 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
 
       while (unwind_sc.GetParentOfInlinedScope(
           curr_frame_address, next_frame_sc, next_frame_address)) {
-        next_frame_sc.line_entry.ApplyFileMappings(target_sp);
+        next_frame_sc.line_entry.ApplyFileMappings(target_sp,
+                                                   unwind_sc.module_sp);
         behaves_like_zeroth_frame = false;
         StackFrameSP frame_sp(new StackFrame(
             m_thread.shared_from_this(), m_frames.size(), idx,
diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp
index de4cd5995f6953..773af67b49ff9a 100644
--- a/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -430,8 +430,11 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
                 new SupportFile(call_site_file_spec));
             top_most_line_entry.range = range;
             top_most_line_entry.file_sp.reset();
-            top_most_line_entry.ApplyFileMappings(
-                GetThread().CalculateTarget());
+
+            lldb::ModuleSP module_sp =
+                run_to_address.CalculateSymbolContextModule();
+            top_most_line_entry.ApplyFileMappings(GetThread().CalculateTarget(),
+                                                  module_sp);
             if (!top_most_line_entry.file_sp)
               top_most_line_entry.file_sp =
                   top_most_line_entry.original_file_sp;
diff --git a/lldb/unittests/Symbol/CMakeLists.txt b/lldb/unittests/Symbol/CMakeLists.txt
index e1d24357e33db0..25de6e6fde9819 100644
--- a/lldb/unittests/Symbol/CMakeLists.txt
+++ b/lldb/unittests/Symbol/CMakeLists.txt
@@ -19,6 +19,7 @@ add_lldb_unittest(SymbolTests
     lldbUtilityHelpers
     lldbPluginObjectFileELF
     lldbPluginObjectFileMachO
+    lldbPluginPlatformLinux
     lldbPluginSymbolFileDWARF
     lldbPluginSymbolFileSymtab
     lldbPluginTypeSystemClang
@@ -26,6 +27,7 @@ add_lldb_unittest(SymbolTests
   )
 
 set(test_inputs
+  inlined-functions.cpp
   inlined-functions.yaml
   )
 add_unittest_inputs(SymbolTests "${test_inputs}")
diff --git a/lldb/unittests/Symbol/Inputs/inlined-functions.cpp b/lldb/unittests/Symbol/Inputs/inlined-functions.cpp
new file mode 100644
index 00000000000000..7d8f53371721cb
--- /dev/null
+++ b/lldb/unittests/Symbol/Inputs/inlined-functions.cpp
@@ -0,0 +1,22 @@
+inline __attribute__((always_inline)) int sum2(int a, int b) {
+  int result = a + b;
+  return result;
+}
+
+int sum3(int a, int b, int c) {
+  int result = a + b + c;
+  return result;
+}
+
+inline __attribute__((always_inline)) int sum4(int a, int b, int c, int d) {
+  int result = sum2(a, b) + sum2(c, d);
+  result += 0;
+  return result;
+}
+
+int main(int argc, char **argv) {
+  sum3(3, 4, 5) + sum2(1, 2);
+  int sum = sum4(1, 2, 3, 4);
+  sum2(5, 6);
+  return 0;
+}
diff --git a/lldb/unittests/Symbol/TestLineEntry.cpp b/lldb/unittests/Symbol/TestLineEntry.cpp
index 592504bc2198ab..92454d55ae8ea7 100644
--- a/lldb/unittests/Symbol/TestLineEntry.cpp
+++ b/lldb/unittests/Symbol/TestLineEntry.cpp
@@ -11,13 +11,16 @@
 #include <optional>
 
 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
+#include "Plugins/Platform/Linux/PlatformLinux.h"
 #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 
+#include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Symbol/CompileUnit.h"
@@ -29,21 +32,36 @@
 
 using namespace lldb;
 using namespace lldb_private;
+using namespace lldb_private::platform_linux;
 using namespace lldb_private::plugin::dwarf;
+using namespace testing;
+
+namespace {
+
+constexpr llvm::StringLiteral k_source_file("inlined-functions.cpp");
 
 class LineEntryTest : public testing::Test {
-  SubsystemRAII<FileSystem, HostInfo, ObjectFileMachO, SymbolFileDWARF,
-                TypeSystemClang>
+  SubsystemRAII<FileSystem, HostInfo, ObjectFileMachO, PlatformLinux,
+                SymbolFileDWARF, TypeSystemClang>
       subsystem;
 
 public:
   void SetUp() override;
+  void TearDown() override;
 
 protected:
   llvm::Expected<SymbolContextList>
   GetLineEntriesForLine(uint32_t line, std::optional<uint16_t> column);
+  void CheckNoCallback();
+  void CheckCallbackWithArgs(const ModuleSP &module_sp,
+                             const FileSpec &resolved_file_spec,
+                             const ModuleSP &expected_module_sp);
+  FileSpec GetTestSourceFile();
   std::optional<TestFile> m_file;
   ModuleSP m_module_sp;
+  DebuggerSP m_debugger_sp;
+  PlatformSP m_platform_sp;
+  TargetSP m_target_sp;
 };
 
 void LineEntryTest::SetUp() {
@@ -51,6 +69,59 @@ void LineEntryTest::SetUp() {
   ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
   m_file.emplace(std::move(*ExpectedFile));
   m_module_sp = std::make_shared<Module>(m_file->moduleSpec());
+
+  // Create Debugger.
+  m_debugger_sp = Debugger::CreateInstance();
+  EXPECT_TRUE(m_debugger_sp);
+
+  // Create Platform.
+  ArchSpec host_arch("i386-pc-linux");
+  m_platform_sp =
+      platform_linux::PlatformLinux::CreateInstance(true, &host_arch);
+  Platform::SetHostPlatform(m_platform_sp);
+  EXPECT_TRUE(m_platform_sp);
+
+  // Create Target.
+  m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", host_arch,
+                                              eLoadDependentsNo, m_platform_sp,
+                                              m_target_sp);
+  EXPECT_TRUE(m_target_sp);
+
+  m_target_sp->SetExecutableModule(m_module_sp);
+}
+
+void LineEntryTest::TearDown() {
+  if (m_module_sp) {
+    ModuleList::RemoveSharedModule(m_module_sp);
+  }
+}
+
+void LineEntryTest::CheckNoCallback() {
+  EXPECT_FALSE(m_platform_sp->GetResolveSourceFileCallback());
+}
+
+void LineEntryTest::CheckCallbackWithArgs(const ModuleSP &module_sp,
+                                          const FileSpec &resolved_file_spec,
+                                          const ModuleSP &expected_module_sp) {
+  EXPECT_TRUE(module_sp == expected_module_sp);
+  EXPECT_FALSE(resolved_file_spec);
+}
+
+FileSpec LineEntryTest::GetTestSourceFile() {
+  const auto *info = UnitTest::GetInstance()->current_test_info();
+  FileSpec test_file = HostInfo::GetProcessTempDir();
+  test_file.AppendPathComponent(std::string(info->test_case_name()) + "-" +
+                                info->name());
+  test_file.AppendPathComponent(k_source_file);
+
+  std::error_code ec =
+      llvm::sys::fs::create_directory(test_file.GetDirectory().GetCString());
+  EXPECT_FALSE(ec);
+
+  ec = llvm::sys::fs::copy_file(GetInputFilePath(k_source_file),
+                                test_file.GetPath().c_str());
+  EXPECT_FALSE(ec);
+  return test_file;
 }
 
   // TODO: Handle SourceLocationSpec column information
@@ -78,6 +149,8 @@ llvm::Expected<SymbolContextList> LineEntryTest::GetLineEntriesForLine(
   return sc_line_entries;
 }
 
+} // end namespace
+
 // This tests if we can get all line entries that match the passed line, if
 // no column is specified.
 TEST_F(LineEntryTest, GetAllExactLineMatchesWithoutColumn) {
@@ -125,6 +198,93 @@ TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeNestedInline) {
   ASSERT_EQ(range.GetByteSize(), (uint64_t)0x33);
 }
 
+TEST_F(LineEntryTest, ResolveSourceFileCallbackNotSetTest) {
+  // Resolve source file callback is not set. ApplyFileMappings should succeed
+  // to return the original file spec from line entry
+  auto sc_line_entries = GetLineEntriesForLine(12);
+  ASSERT_THAT_EXPECTED(sc_line_entries, llvm::Succeeded());
+  auto line_entry = sc_line_entries.get()[0].line_entry;
+
+  const lldb::SupportFileSP original_file_sp = line_entry.file_sp;
+  CheckNoCallback();
+
+  line_entry.ApplyFileMappings(m_target_sp, m_module_sp);
+  ASSERT_EQ(line_entry.file_sp, original_file_sp);
+}
+
+TEST_F(LineEntryTest, ResolveSourceFileCallbackSetFailTest) {
+  // Resolve source file callback fails for some reason.
+  // CallResolveSourceFileCallbackIfSet should fail and ApplyFileMappings should
+  // return the original file spec.
+  auto sc_line_entries = GetLineEntriesForLine(12);
+  ASSERT_THAT_EXPECTED(sc_line_entries, llvm::Succeeded());
+  auto line_entry = sc_line_entries.get()[0].line_entry;
+
+  const lldb::SupportFileSP original_file_sp = line_entry.file_sp;
+  m_platform_sp->SetResolveSourceFileCallback(
+      [this](const lldb::ModuleSP &module_sp,
+             const FileSpec &original_file_spec, FileSpec &resolved_file_spec) {
+        CheckCallbackWithArgs(module_sp, resolved_file_spec, m_module_sp);
+        return Status::FromErrorString(
+            "The resolve source file callback failed");
+      });
+
+  line_entry.ApplyFileMappings(m_target_sp, m_module_sp);
+  ASSERT_EQ(line_entry.file_sp, original_file_sp);
+}
+
+TEST_F(LineEntryTest, ResolveSourceFileCallbackSetNonExistentPathTest) {
+  // Resolve source file callback succeeds but returns a non-existent path.
+  // CallResolveSourceFileCallbackIfSet should succeed and ApplyFileMappings
+  // should return the original file spec.
+  auto sc_line_entries = GetLineEntriesForLine(12);
+  ASSERT_THAT_EXPECTED(sc_line_entries, llvm::Succeeded());
+  auto line_entry = sc_line_entries.get()[0].line_entry;
+
+  const lldb::SupportFileSP original_file_sp = line_entry.file_sp;
+  FileSpec callback_file_spec;
+  const FileSpec expected_callback_file_spec =
+      FileSpec("/this path does not exist");
+
+  m_platform_sp->SetResolveSourceFileCallback(
+      [this, &expected_callback_file_spec, &callback_file_spec](
+          const lldb::ModuleSP &module_sp, const FileSpec &original_file_spec,
+          FileSpec &resolved_file_spec) {
+        CheckCallbackWithArgs(module_sp, resolved_file_spec, m_module_sp);
+        resolved_file_spec.SetPath(expected_callback_file_spec.GetPath());
+        callback_file_spec.SetPath(resolved_file_spec.GetPath());
+        return Status();
+      });
+
+  line_entry.ApplyFileMappings(m_target_sp, m_module_sp);
+
+  ASSERT_EQ(callback_file_spec, expected_callback_file_spec);
+  ASSERT_EQ(line_entry.file_sp, original_file_sp);
+}
+
+TEST_F(LineEntryTest, ResolveSourceFileCallbackSetSuccessTest) {
+  // Resolve source file callback is set. CallResolveSourceFileCallbackIfSet
+  // should succeed and ApplyFileMappings should return the new file spec from
+  // the callback.
+  auto sc_line_entries = GetLineEntriesForLine(12);
+  ASSERT_THAT_EXPECTED(sc_line_entries, llvm::Succeeded());
+  auto line_entry = sc_line_entries.get()[0].line_entry;
+
+  const FileSpec expected_callback_file_spec = GetTestSourceFile();
+
+  m_platform_sp->SetResolveSourceFileCallback(
+      [this, &expected_callback_file_spec](const lldb::ModuleSP &module_sp,
+                                           const FileSpec &original_file_spec,
+                                           FileSpec &resolved_file_spec) {
+        CheckCallbackWithArgs(module_sp, resolved_file_spec, m_module_sp);
+        resolved_file_spec.SetPath(expected_callback_file_spec.GetPath());
+        return Status();
+      });
+
+  line_entry.ApplyFileMappings(m_target_sp, m_module_sp);
+  ASSERT_EQ(line_entry.file_sp->GetSpecOnly(), expected_callback_file_spec);
+}
+
 /*
 # inlined-functions.cpp
 inline __attribute__((always_inline)) int sum2(int a, int b) {



More information about the lldb-commits mailing list