[Lldb-commits] [lldb] [llvm] Add support for ondemand sourcefile fetch using python callback (PR #119118)

via lldb-commits lldb-commits at lists.llvm.org
Sat Dec 7 22:53:48 PST 2024


https://github.com/rchamala created https://github.com/llvm/llvm-project/pull/119118

None

>From 1b984ba9747618e277c8ffb2c48467aec7c2a6a3 Mon Sep 17 00:00:00 2001
From: shawbyoung <shawbyoung at gmail.com>
Date: Mon, 10 Jun 2024 12:08:38 -0700
Subject: [PATCH 1/2] [BOLT][NFC] Add sink block to flow CFG in profile
 inference

Test Plan: tbd

Reviewers:
Subscribers:

Tasks:

Tags:

Differential Revision: https://phabricator.intern.facebook.com/D58380996
---
 bolt/lib/Profile/StaleProfileMatching.cpp     | 38 ++++++++++++++++---
 .../Transforms/Utils/SampleProfileInference.h |  3 +-
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp
index 365bc5389266df..8ecfb618072abf 100644
--- a/bolt/lib/Profile/StaleProfileMatching.cpp
+++ b/bolt/lib/Profile/StaleProfileMatching.cpp
@@ -309,22 +309,33 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
   FlowFunction Func;
 
   // Add a special "dummy" source so that there is always a unique entry point.
-  // Because of the extra source, for all other blocks in FlowFunction it holds
-  // that Block.Index == BB->getIndex() + 1
   FlowBlock EntryBlock;
   EntryBlock.Index = 0;
   Func.Blocks.push_back(EntryBlock);
 
+  auto BinaryBlockIsExit = [&](const BinaryBasicBlock &BB) {
+    if (BB.successors().empty())
+      return true;
+    return false;
+  };
+
   // Create FlowBlock for every basic block in the binary function
   for (const BinaryBasicBlock *BB : BlockOrder) {
     Func.Blocks.emplace_back();
     FlowBlock &Block = Func.Blocks.back();
     Block.Index = Func.Blocks.size() - 1;
+    Block.HasSuccessors = BinaryBlockIsExit(*BB);
     (void)BB;
     assert(Block.Index == BB->getIndex() + 1 &&
            "incorrectly assigned basic block index");
   }
 
+  // Add a special "dummy" sink block so there is always a unique sink
+  FlowBlock SinkBlock;
+  SinkBlock.Index = Func.Blocks.size();
+  Func.Blocks.push_back(SinkBlock);
+  Func.Sink = SinkBlock.Index;
+
   // Create FlowJump for each jump between basic blocks in the binary function
   std::vector<uint64_t> InDegree(Func.Blocks.size(), 0);
   for (const BinaryBasicBlock *SrcBB : BlockOrder) {
@@ -360,18 +371,29 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
   // Add dummy edges to the extra sources. If there are multiple entry blocks,
   // add an unlikely edge from 0 to the subsequent ones
   assert(InDegree[0] == 0 && "dummy entry blocks shouldn't have predecessors");
-  for (uint64_t I = 1; I < Func.Blocks.size(); I++) {
+  for (uint64_t I = 1; I < BlockOrder.size() + 1; I++) {
     const BinaryBasicBlock *BB = BlockOrder[I - 1];
     if (BB->isEntryPoint() || InDegree[I] == 0) {
       Func.Jumps.emplace_back();
       FlowJump &Jump = Func.Jumps.back();
-      Jump.Source = 0;
+      Jump.Source = Func.Entry;
       Jump.Target = I;
       if (!BB->isEntryPoint())
         Jump.IsUnlikely = true;
     }
   }
 
+  // Add dummy edges from the exit blocks to the sink block.
+  for (uint64_t I = 1; I < BlockOrder.size() + 1; I++) {
+    FlowBlock &Block = Func.Blocks[I];
+    if (Block.HasSuccessors) {
+      Func.Jumps.emplace_back();
+      FlowJump &Jump = Func.Jumps.back();
+      Jump.Source = I;
+      Jump.Target = Func.Sink;
+    }
+  }
+
   // Create necessary metadata for the flow function
   for (FlowJump &Jump : Func.Jumps) {
     assert(Jump.Source < Func.Blocks.size());
@@ -379,6 +401,7 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
     assert(Jump.Target < Func.Blocks.size());
     Func.Blocks[Jump.Target].PredJumps.push_back(&Jump);
   }
+
   return Func;
 }
 
@@ -395,7 +418,7 @@ void matchWeightsByHashes(BinaryContext &BC,
                           const BinaryFunction::BasicBlockOrderType &BlockOrder,
                           const yaml::bolt::BinaryFunctionProfile &YamlBF,
                           FlowFunction &Func) {
-  assert(Func.Blocks.size() == BlockOrder.size() + 1);
+  assert(Func.Blocks.size() == BlockOrder.size() + 2);
 
   std::vector<FlowBlock *> Blocks;
   std::vector<BlendedBlockHash> BlendedHashes;
@@ -618,7 +641,7 @@ void assignProfile(BinaryFunction &BF,
                    FlowFunction &Func) {
   BinaryContext &BC = BF.getBinaryContext();
 
-  assert(Func.Blocks.size() == BlockOrder.size() + 1);
+  assert(Func.Blocks.size() == BlockOrder.size() + 2);
   for (uint64_t I = 0; I < BlockOrder.size(); I++) {
     FlowBlock &Block = Func.Blocks[I + 1];
     BinaryBasicBlock *BB = BlockOrder[I];
@@ -640,6 +663,9 @@ void assignProfile(BinaryFunction &BF,
       if (Jump->Flow == 0)
         continue;
 
+      // Skip the artificial sink block
+      if (Jump->Target == Func.Sink)
+        continue;
       BinaryBasicBlock &SuccBB = *BlockOrder[Jump->Target - 1];
       // Check if the edge corresponds to a regular jump or a landing pad
       if (BB->getSuccessor(SuccBB.getLabel())) {
diff --git a/llvm/include/llvm/Transforms/Utils/SampleProfileInference.h b/llvm/include/llvm/Transforms/Utils/SampleProfileInference.h
index b4ea1ad840f9d9..b2af05a24c7055 100644
--- a/llvm/include/llvm/Transforms/Utils/SampleProfileInference.h
+++ b/llvm/include/llvm/Transforms/Utils/SampleProfileInference.h
@@ -31,10 +31,10 @@ struct FlowBlock {
   uint64_t Flow{0};
   std::vector<FlowJump *> SuccJumps;
   std::vector<FlowJump *> PredJumps;
+  bool HasSuccessors{false};
 
   /// Check if it is the entry block in the function.
   bool isEntry() const { return PredJumps.empty(); }
-
   /// Check if it is an exit block in the function.
   bool isExit() const { return SuccJumps.empty(); }
 };
@@ -57,6 +57,7 @@ struct FlowFunction {
   std::vector<FlowJump> Jumps;
   /// The index of the entry block.
   uint64_t Entry{0};
+  uint64_t Sink{0};
 };
 
 /// Various thresholds and options controlling the behavior of the profile

>From 5a97d761a5e2e0b112e54cfb988418b97d350d9f Mon Sep 17 00:00:00 2001
From: Rahul Reddy Chamala <rachamal at fb.com>
Date: Mon, 30 Sep 2024 12:26:41 -0700
Subject: [PATCH 2/2] Add support for ondemand sourcefile fetch using python
 callback

Summary:

Test Plan:

Reviewers:

Subscribers:

Tasks:

Tags:


Differential Revision: https://phabricator.intern.facebook.com/D66931972
---
 lldb/bindings/python/python-typemaps.swig | 44 ++++++++++++++++++
 lldb/bindings/python/python-wrapper.swig  | 48 +++++++++++++++++++-
 lldb/include/lldb/API/SBDefines.h         |  8 +++-
 lldb/include/lldb/API/SBPlatform.h        |  3 ++
 lldb/include/lldb/Symbol/LineEntry.h      |  3 +-
 lldb/include/lldb/Target/Platform.h       | 14 ++++++
 lldb/source/API/SBPlatform.cpp            | 36 +++++++++++++++
 lldb/source/Symbol/LineEntry.cpp          | 44 +++++++++++++++++-
 lldb/source/Target/Platform.cpp           | 54 +++++++++++++++++++++++
 lldb/source/Target/StackFrame.cpp         |  2 +-
 lldb/source/Target/StackFrameList.cpp     |  3 +-
 11 files changed, 253 insertions(+), 6 deletions(-)

diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig
index 8d4b740e5f35ca..787787994a62c9 100644
--- a/lldb/bindings/python/python-typemaps.swig
+++ b/lldb/bindings/python/python-typemaps.swig
@@ -696,3 +696,47 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
   $1 = $input == Py_None;
   $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
 }
+
+// For lldb::SBPlatformResolveSourceFileCallback
+%typemap(in) (lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton) {
+  if (!($input == Py_None ||
+       PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
+        PyErr_SetString(PyExc_TypeError, "Need a callable object or None!");
+        SWIG_fail;
+       }
+
+  if ($input == Py_None) {
+    $1 = nullptr;
+    $2 = nullptr;
+  } else {
+    PythonCallable callable = Retain<PythonCallable>($input);
+    if (!callable.IsValid()) {
+      PyErr_SetString(PyExc_TypeError, "Need a valid callable object");
+      SWIG_fail;
+    }
+
+  llvm::Expected<PythonCallable::ArgInfo> arg_info = callable.GetArgInfo();
+  if (!arg_info) {
+    PyErr_SetString(PyExc_TypeError,
+                      ("Could not get arguments: " +
+                          llvm::toString(arg_info.takeError())).c_str());
+      SWIG_fail;
+  }
+
+  if (arg_info.get().max_positional_args != 3) {
+    PyErr_SetString(PyExc_TypeError, "Expected 3 argument callable object");
+    SWIG_fail;
+  }
+
+    Py_INCREF($input);
+
+    $1 = LLDBSwigPythonCallResolveSourceFileCallback;
+    $2 = $input;
+  }
+}
+
+%typemap(typecheck) (lldb::SBPlatformResolveSourceFileCallback callback,
+                     void *callback_baton) {
+  $1 = $input == Py_None;
+  $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
+}
diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index 1370afc885d43f..e10b8c5a9481e7 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -844,7 +844,7 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallParsedCommandObject(
   auto pfunc = self.ResolveName<PythonCallable>("__call__");
 
   if (!pfunc.IsAllocated()) {
-    cmd_retobj.AppendError("Could not find '__call__' method in implementation class"); 
+    cmd_retobj.AppendError("Could not find '__call__' method in implementation class");
     return false;
   }
 
@@ -1148,4 +1148,50 @@ static SBError LLDBSwigPythonCallLocateModuleCallback(
 
   return *sb_error_ptr;
 }
+
+static SBError LLDBSwigPythonCallResolveSourceFileCallback(
+    void *callback_baton,
+    const char* build_id,
+    const SBFileSpec &original_source_file_spec_sb,
+    SBFileSpec &resolved_source_file_spec_sb) {
+  SWIG_Python_Thread_Block swig_thread_block;
+
+  PyErr_Cleaner py_err_cleaner(true);
+
+  PyObject *py_build_id = PyUnicode_FromString(build_id);
+  PythonObject build_id_arg(PyRefType::Borrowed,py_build_id);
+  PythonObject original_source_file_spec_arg = SWIGBridge::ToSWIGWrapper(
+      std::make_unique<SBFileSpec>(original_source_file_spec_sb));
+  PythonObject resolved_source_file_spec_arg = SWIGBridge::ToSWIGWrapper(
+      std::make_unique<SBFileSpec>(resolved_source_file_spec_sb));
+
+  PythonCallable callable =
+      Retain<PythonCallable>(reinterpret_cast<PyObject *>(callback_baton));
+  if (!callable.IsValid()) {
+    return SBError("The callback callable is not valid.");
+  }
+
+  PythonObject result = callable(build_id_arg, original_source_file_spec_arg,
+                                 resolved_source_file_spec_arg);
+
+  if (!result.IsAllocated())
+    return SBError("No result.");
+  lldb::SBError *sb_error_ptr = nullptr;
+  if (SWIG_ConvertPtr(result.get(), (void **)&sb_error_ptr,
+                      SWIGTYPE_p_lldb__SBError, 0) == -1) {
+    return SBError("Result is not SBError.");
+  }
+
+  if (sb_error_ptr->Success()) {
+    lldb::SBFileSpec *sb_resolved_source_file_spec_ptr = nullptr;
+    if (SWIG_ConvertPtr(resolved_source_file_spec_arg.get(),
+                        (void **)&sb_resolved_source_file_spec_ptr,
+                        SWIGTYPE_p_lldb__SBFileSpec, 0) == -1)
+      return SBError("resolved_source_file_spec is not SBFileSpec.");
+
+    resolved_source_file_spec_sb = *sb_resolved_source_file_spec_ptr;
+  }
+
+  return *sb_error_ptr;
+}
 %}
diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h
index 87c0a1c3661ca3..94ba0082c7bc7f 100644
--- a/lldb/include/lldb/API/SBDefines.h
+++ b/lldb/include/lldb/API/SBDefines.h
@@ -12,6 +12,7 @@
 #include "lldb/lldb-defines.h"
 #include "lldb/lldb-enumerations.h"
 #include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
 #include "lldb/lldb-types.h"
 #include "lldb/lldb-versioning.h"
 
@@ -141,9 +142,14 @@ typedef bool (*SBBreakpointHitCallback)(void *baton, SBProcess &process,
 typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id,
                                           void *baton);
 
-typedef SBError (*SBPlatformLocateModuleCallback)(
+typedef lldb::SBError (*SBPlatformLocateModuleCallback)(
     void *baton, const SBModuleSpec &module_spec, SBFileSpec &module_file_spec,
     SBFileSpec &symbol_file_spec);
+
+typedef lldb::SBError (*SBPlatformResolveSourceFileCallback)(
+    void *baton, const char *buildId,
+    const SBFileSpec &original_source_file_spec,
+    SBFileSpec &resolved_source_file_spec);
 }
 
 #endif // LLDB_API_SBDEFINES_H
diff --git a/lldb/include/lldb/API/SBPlatform.h b/lldb/include/lldb/API/SBPlatform.h
index d63d2ed1eaba62..37ab2ef0441cf5 100644
--- a/lldb/include/lldb/API/SBPlatform.h
+++ b/lldb/include/lldb/API/SBPlatform.h
@@ -190,6 +190,9 @@ class LLDB_API SBPlatform {
   SBError SetLocateModuleCallback(lldb::SBPlatformLocateModuleCallback callback,
                                   void *callback_baton);
 
+  SBError SetResolveSourceFileCallback(
+      lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton);
+
 protected:
   friend class SBDebugger;
   friend class SBTarget;
diff --git a/lldb/include/lldb/Symbol/LineEntry.h b/lldb/include/lldb/Symbol/LineEntry.h
index 8da59cf0bd24aa..38916d31b31f4e 100644
--- a/lldb/include/lldb/Symbol/LineEntry.h
+++ b/lldb/include/lldb/Symbol/LineEntry.h
@@ -128,7 +128,7 @@ struct LineEntry {
   ///
   /// \param[in] target_sp
   ///     Shared pointer to the target this LineEntry belongs to.
-  void ApplyFileMappings(lldb::TargetSP target_sp);
+  void ApplyFileMappings(lldb::TargetSP target_sp, const Address &address);
 
   /// Helper to access the file.
   const FileSpec &GetFile() const { return file_sp->GetSpecOnly(); }
@@ -181,6 +181,7 @@ struct LineEntry {
 ///     Returns \b true if lhs < rhs, false otherwise.
 bool operator<(const LineEntry &lhs, const LineEntry &rhs);
 
+// Add signature for CallFetchSourceFileCallBack
 } // namespace lldb_private
 
 #endif // LLDB_SYMBOL_LINEENTRY_H
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index e05c79cb501bf0..85d208c4752320 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -329,6 +329,10 @@ class Platform : public PluginInterface {
   virtual bool GetModuleSpec(const FileSpec &module_file_spec,
                              const ArchSpec &arch, ModuleSpec &module_spec);
 
+  void CallResolveSourceFileCallbackIfSet(
+      const char *build_id, const FileSpec &original_source_file_spec,
+      FileSpec &resolved_source_file_spec, bool *did_create_ptr);
+
   virtual Status ConnectRemote(Args &args);
 
   virtual Status DisconnectRemote();
@@ -921,6 +925,11 @@ class Platform : public PluginInterface {
                                FileSpec &symbol_file_spec)>
       LocateModuleCallback;
 
+  typedef std::function<Status(const char *buildId,
+                               const FileSpec &original_fileSpec,
+                               FileSpec &newFileSpec)>
+      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
@@ -929,6 +938,10 @@ class Platform : public PluginInterface {
 
   LocateModuleCallback GetLocateModuleCallback() const;
 
+  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".
@@ -977,6 +990,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/API/SBPlatform.cpp b/lldb/source/API/SBPlatform.cpp
index 3623fd35bcdf13..b01a396091f9fa 100644
--- a/lldb/source/API/SBPlatform.cpp
+++ b/lldb/source/API/SBPlatform.cpp
@@ -734,3 +734,39 @@ SBError SBPlatform::SetLocateModuleCallback(
       });
   return SBError();
 }
+
+SBError SBPlatform::SetResolveSourceFileCallback(
+    lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton) {
+  LLDB_INSTRUMENT_VA(this, callback, callback_baton);
+  PlatformSP platform_sp(GetSP());
+  if (!platform_sp) {
+    return SBError("invalid platform");
+  }
+
+  if (!callback) {
+    // Clear the callback.
+    platform_sp->SetResolveSourceFileCallback(nullptr);
+    return SBError("invalid callback");
+  }
+
+  // Platform.h does not accept lldb::SBPlatformFetchSourceFileCallback
+  // directly because of the SBFileSpec dependencies. Use a lambda to convert
+  // FileSpec <--> SBFileSpec for the callback arguments.
+  platform_sp->SetResolveSourceFileCallback(
+      [callback, callback_baton](const char *build_id,
+                                 const FileSpec &original_source_file_spec,
+                                 FileSpec &resolved_source_file_spec) {
+        SBFileSpec resolved_source_file_spec_sb(resolved_source_file_spec);
+
+        SBError error =
+            callback(callback_baton, build_id, original_source_file_spec,
+                     resolved_source_file_spec_sb);
+
+        if (error.Success()) {
+          resolved_source_file_spec = resolved_source_file_spec_sb.ref();
+        }
+
+        return error.ref();
+      });
+  return SBError();
+}
diff --git a/lldb/source/Symbol/LineEntry.cpp b/lldb/source/Symbol/LineEntry.cpp
index 461399e0326e91..c175f3ace6d309 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"
 
@@ -240,8 +243,47 @@ AddressRange LineEntry::GetSameLineContiguousAddressRange(
   return complete_line_range;
 }
 
-void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) {
+void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp,
+                                  const Address &address) {
   if (target_sp) {
+
+    SymbolContext sc;
+    target_sp->GetImages().ResolveSymbolContextForAddress(
+        address, lldb::eSymbolContextModule, sc);
+    lldb::ModuleSP module_sp = sc.module_sp;
+
+    auto spec = original_file_sp->GetSpecOnly();
+    std::string path = spec.GetPath();
+
+    if (module_sp) {
+      ObjectFile *obj_file = module_sp->GetObjectFile();
+      module_sp->GetFileSpec();
+      if (obj_file) {
+
+        UUID build_id = obj_file->GetUUID();
+        auto buildId_string = new std::string(build_id.GetAsString());
+
+        const char *build_id_ptr = buildId_string->c_str();
+
+        FileSpec newSpec;
+        // Fetches the new spec file
+        bool *didFetchSourceFile = new bool(false);
+
+        lldb::PlatformSP platform_sp = target_sp->GetPlatform();
+        if (!platform_sp)
+          return;
+
+        FileSpec resolved_source_file_spec;
+        platform_sp->CallResolveSourceFileCallbackIfSet(
+            build_id_ptr, spec, resolved_source_file_spec, didFetchSourceFile);
+        if (didFetchSourceFile) {
+          original_file_sp =
+              std::make_shared<SupportFile>(resolved_source_file_spec);
+          file_sp = std::make_shared<SupportFile>(resolved_source_file_spec);
+        }
+      }
+    }
+
     // Apply any file remappings to our file.
     if (auto new_file_spec = target_sp->GetSourcePathMap().FindFile(
             original_file_sp->GetSpecOnly()))
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index ee1f92470e162e..f2dc82ab515b30 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -1756,6 +1756,50 @@ void Platform::CallLocateModuleCallbackIfSet(const ModuleSpec &module_spec,
   }
 }
 
+void Platform::CallResolveSourceFileCallbackIfSet(
+    const char *build_id, const FileSpec &original_source_file_spec,
+    FileSpec &resolved_source_file_spec, bool *did_create_ptr) {
+  if (!m_resolve_source_file_callback) {
+    // Fetch source file callback is not set.
+    return;
+  }
+
+  FileSpec module_file_spec;
+  Status error = m_resolve_source_file_callback(
+      build_id, original_source_file_spec, resolved_source_file_spec);
+
+  // Fetch source file callback is set and called. Check the error.
+  Log *log = GetLog(LLDBLog::Platform);
+  if (error.Fail()) {
+    LLDB_LOGF(log, "%s: Fetch source file callback failed: %s",
+              LLVM_PRETTY_FUNCTION, error.AsCString());
+    return;
+  }
+
+  if (!resolved_source_file_spec) {
+    LLDB_LOGF(log,
+              "%s: fetch 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: fetch 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;
+  }
+
+  *did_create_ptr = true;
+}
+
 bool Platform::GetCachedSharedModule(const ModuleSpec &module_spec,
                                      lldb::ModuleSP &module_sp,
                                      bool *did_create_ptr) {
@@ -2161,6 +2205,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 3a2b4d05b28810..988f66f038c258 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -395,7 +395,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, lookup_addr);
         }
       }
     } else {
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index 314b5e39c71699..e676e3c4053816 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -551,7 +551,8 @@ bool StackFrameList::GetFramesUpTo(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,
+                                                   curr_frame_address);
         behaves_like_zeroth_frame = false;
         StackFrameSP frame_sp(new StackFrame(
             m_thread.shared_from_this(), m_frames.size(), idx,



More information about the lldb-commits mailing list