Skip to content

[lldb][Platform] Handle LoadScriptFromSymFile per-module FileSpec - #189696

Merged
Michael137 merged 2 commits into
llvm:mainfrom
Michael137:lldb/auto-load-style-per-module
Mar 31, 2026
Merged

[lldb][Platform] Handle LoadScriptFromSymFile per-module FileSpec#189696
Michael137 merged 2 commits into
llvm:mainfrom
Michael137:lldb/auto-load-style-per-module

Conversation

@Michael137

Copy link
Copy Markdown
Member

This patch changes the Platform::LocateXXX to return a map from FileSpec to LoadScriptFromSymFile enum.

This is needed for #188722, where I intend to set LoadScriptFromSymFile per-module.

By default the Platform::LocateXXX set the value to whatever the target's current target.load-script-from-symbol-file is set to. In #188722 we'll allow overriding this per-target setting on a per-module basis.

Drive-by:

  • Added logging when we fail to load a script.

@llvmbot

llvmbot commented Mar 31, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-lldb

Author: Michael Buch (Michael137)

Changes

This patch changes the Platform::LocateXXX to return a map from FileSpec to LoadScriptFromSymFile enum.

This is needed for #188722, where I intend to set LoadScriptFromSymFile per-module.

By default the Platform::LocateXXX set the value to whatever the target's current target.load-script-from-symbol-file is set to. In #188722 we'll allow overriding this per-target setting on a per-module basis.

Drive-by:

  • Added logging when we fail to load a script.

Patch is 33.31 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/189696.diff

7 Files Affected:

  • (modified) lldb/include/lldb/Target/Platform.h (+10-8)
  • (modified) lldb/source/Core/Module.cpp (+7-14)
  • (modified) lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp (+15-11)
  • (modified) lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h (+7-4)
  • (modified) lldb/source/Target/Platform.cpp (+18-12)
  • (modified) lldb/unittests/Platform/PlatformDarwinTest.cpp (+69-84)
  • (modified) lldb/unittests/Platform/PlatformTest.cpp (+70-67)
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index 3d0776d95b539..6bdaf10ef0713 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -273,15 +273,15 @@ class Platform : public PluginInterface {
 
   /// Locate the scripting resource given a module specification.
   ///
-  /// Locating the file should happen only on the local computer or using the
-  /// current computers global settings.
-  FileSpecList LocateExecutableScriptingResources(Target *target,
-                                                  Module &module,
-                                                  Stream &feedback_stream);
+  /// Returns a map from a located script's \c FileSpec to the
+  /// \c LoadScriptFromSymFile with which LLDB should load it.
+  llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
+  LocateExecutableScriptingResources(Target *target, Module &module,
+                                     Stream &feedback_stream);
 
   /// Locate the platform-specific scripting resource given a module
   /// specification.
-  virtual FileSpecList
+  virtual llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
   LocateExecutableScriptingResourcesForPlatform(Target *target, Module &module,
                                                 Stream &feedback_stream);
 
@@ -291,8 +291,10 @@ class Platform : public PluginInterface {
   ///
   /// E.g., for Python it will look for a script at:
   ///   \c <safe-path>/<module-name>/<module-name>.py
-  static FileSpecList LocateExecutableScriptingResourcesFromSafePaths(
-      Stream &feedback_stream, FileSpec module_spec, const Target &target);
+  static llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
+  LocateExecutableScriptingResourcesFromSafePaths(Stream &feedback_stream,
+                                                  FileSpec module_spec,
+                                                  const Target &target);
 
   /// \param[in] module_spec
   ///     The ModuleSpec of a binary to find.
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 3d33a5011fb5e..455d50c965d72 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -1439,12 +1439,6 @@ bool Module::LoadScriptingResourceInTarget(Target *target, Status &error) {
     return false;
   }
 
-  LoadScriptFromSymFile should_load =
-      target->TargetProperties::GetLoadScriptFromSymbolFile();
-
-  if (should_load == eLoadScriptFromSymFileFalse)
-    return false;
-
   Debugger &debugger = target->GetDebugger();
   const ScriptLanguage script_language = debugger.GetScriptLanguage();
   if (script_language == eScriptLanguageNone)
@@ -1464,22 +1458,21 @@ bool Module::LoadScriptingResourceInTarget(Target *target, Status &error) {
   }
 
   StreamString feedback_stream;
-  FileSpecList file_specs = platform_sp->LocateExecutableScriptingResources(
-      target, *this, feedback_stream);
+  llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile> file_specs =
+      platform_sp->LocateExecutableScriptingResources(target, *this,
+                                                      feedback_stream);
 
   if (!feedback_stream.Empty())
     debugger.ReportWarning(feedback_stream.GetString().str(), debugger.GetID());
 
-  const uint32_t num_specs = file_specs.GetSize();
-  if (num_specs == 0)
-    return true;
+  for (const auto &[scripting_fspec, load_style] : file_specs) {
+    if (load_style == eLoadScriptFromSymFileFalse)
+      continue;
 
-  for (uint32_t i = 0; i < num_specs; ++i) {
-    FileSpec scripting_fspec(file_specs.GetFileSpecAtIndex(i));
     if (!FileSystem::Instance().Exists(scripting_fspec))
       continue;
 
-    if (should_load == eLoadScriptFromSymFileWarn) {
+    if (load_style == eLoadScriptFromSymFileWarn) {
       // clang-format off
       debugger.ReportWarning(
           llvm::formatv(
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 98f0025303ac1..c6351b02791db 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -196,7 +196,8 @@ PlatformDarwin::PutFile(const lldb_private::FileSpec &source,
   return PlatformPOSIX::PutFile(source, destination, uid, gid);
 }
 
-FileSpecList PlatformDarwin::LocateExecutableScriptingResourcesFromDSYM(
+llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
+PlatformDarwin::LocateExecutableScriptingResourcesFromDSYM(
     Stream &feedback_stream, FileSpec module_spec, const Target &target,
     const FileSpec &symfile_spec) {
 
@@ -204,7 +205,7 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResourcesFromDSYM(
          "Trying to locate scripting resources but no ScriptInterpreter is "
          "available.");
 
-  FileSpecList file_list;
+  llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile> file_specs;
   while (module_spec.GetFilename()) {
     ScriptInterpreter::SanitizedScriptingModuleName sanitized_name =
         target.GetDebugger()
@@ -234,7 +235,8 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResourcesFromDSYM(
                                          orig_script_fspec, script_fspec);
 
     if (FileSystem::Instance().Exists(script_fspec)) {
-      file_list.Append(script_fspec);
+      file_specs.try_emplace(std::move(script_fspec),
+                             target.GetLoadScriptFromSymbolFile());
       break;
     }
 
@@ -248,17 +250,19 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResourcesFromDSYM(
     module_spec.SetFilename(filename_no_extension);
   }
 
-  return file_list;
+  return file_specs;
 }
 
-FileSpecList PlatformDarwin::LocateExecutableScriptingResourcesForPlatform(
+llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
+PlatformDarwin::LocateExecutableScriptingResourcesForPlatform(
     Target *target, Module &module, Stream &feedback_stream) {
+  llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile> file_specs;
   if (!target)
-    return {};
+    return file_specs;
 
   // For now only Python scripts supported for auto-loading.
   if (target->GetDebugger().GetScriptLanguage() != eScriptLanguagePython)
-    return {};
+    return file_specs;
 
   // NB some extensions might be meaningful and should not be stripped -
   // "this.binary.file"
@@ -270,15 +274,15 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResourcesForPlatform(
   const FileSpec &module_spec = module.GetFileSpec();
 
   if (!module_spec)
-    return {};
+    return file_specs;
 
   SymbolFile *symfile = module.GetSymbolFile();
   if (!symfile)
-    return {};
+    return file_specs;
 
   ObjectFile *objfile = symfile->GetObjectFile();
   if (!objfile)
-    return {};
+    return file_specs;
 
   const FileSpec &symfile_spec = objfile->GetFileSpec();
   if (symfile_spec &&
@@ -288,7 +292,7 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResourcesForPlatform(
     return LocateExecutableScriptingResourcesFromDSYM(
         feedback_stream, module_spec, *target, symfile_spec);
 
-  return {};
+  return file_specs;
 }
 
 Status PlatformDarwin::ResolveSymbolFile(Target &target,
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
index 2b0b7ad4b827d..3c98d420dde8c 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -67,7 +67,8 @@ class PlatformDarwin : public PlatformPOSIX {
   Status ResolveSymbolFile(Target &target, const ModuleSpec &sym_spec,
                            FileSpec &sym_file) override;
 
-  FileSpecList LocateExecutableScriptingResourcesForPlatform(
+  llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
+  LocateExecutableScriptingResourcesForPlatform(
       Target *target, Module &module_spec, Stream &feedback_stream) override;
 
   Status GetSharedModule(const ModuleSpec &module_spec, Process *process,
@@ -150,9 +151,11 @@ class PlatformDarwin : public PlatformPOSIX {
   /// Resources directory in the same dSYM.
   /// E.g., \c /path/to/.dSYM/Contents/Resources/DWARF/a.out
   ///
-  static FileSpecList LocateExecutableScriptingResourcesFromDSYM(
-      Stream &feedback_stream, FileSpec module_spec, const Target &target,
-      const FileSpec &symfile_spec);
+  static llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
+  LocateExecutableScriptingResourcesFromDSYM(Stream &feedback_stream,
+                                             FileSpec module_spec,
+                                             const Target &target,
+                                             const FileSpec &symfile_spec);
 
 protected:
   static const char *GetCompatibleArch(ArchSpec::Core core, size_t idx);
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index 51ef8d7259d9a..a676c50ef77ed 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -157,14 +157,17 @@ Status Platform::GetFileWithUUID(const FileSpec &platform_file,
   return Status();
 }
 
-FileSpecList Platform::LocateExecutableScriptingResourcesFromSafePaths(
+llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
+Platform::LocateExecutableScriptingResourcesFromSafePaths(
     Stream &feedback_stream, FileSpec module_spec, const Target &target) {
   assert(module_spec);
   assert(target.GetDebugger().GetScriptInterpreter());
 
+  llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile> file_specs;
+
   // For now only Python scripts supported for auto-loading.
   if (target.GetDebugger().GetScriptLanguage() != eScriptLanguagePython)
-    return {};
+    return file_specs;
 
   ScriptInterpreter::SanitizedScriptingModuleName sanitized_name =
       target.GetDebugger()
@@ -172,7 +175,6 @@ FileSpecList Platform::LocateExecutableScriptingResourcesFromSafePaths(
           ->GetSanitizedScriptingModuleName(
               module_spec.GetFileNameStrippingExtension().GetStringRef());
 
-  FileSpecList file_list;
   FileSpecList paths = Debugger::GetSafeAutoLoadPaths();
 
   // Iterate in reverse so we consider the latest appended path first.
@@ -197,36 +199,40 @@ FileSpecList Platform::LocateExecutableScriptingResourcesFromSafePaths(
                                          orig_script_fspec, script_fspec);
 
     if (FileSystem::Instance().Exists(script_fspec))
-      file_list.Append(script_fspec);
+      file_specs.try_emplace(std::move(script_fspec),
+                             target.GetLoadScriptFromSymbolFile());
 
     // If we successfully found a directory in a safe auto-load path
     // stop looking at any other paths.
     break;
   }
 
-  return file_list;
+  return file_specs;
 }
 
-FileSpecList Platform::LocateExecutableScriptingResourcesForPlatform(
+llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
+Platform::LocateExecutableScriptingResourcesForPlatform(
     Target *target, Module &module, Stream &feedback_stream) {
-  return {};
+  llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile> empty;
+  return empty;
 }
 
-FileSpecList
+llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>
 Platform::LocateExecutableScriptingResources(Target *target, Module &module,
                                              Stream &feedback_stream) {
+  llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile> empty;
   if (!target)
-    return {};
+    return empty;
 
   // Give derived platforms a chance to locate scripting resources.
-  if (FileSpecList fspecs = LocateExecutableScriptingResourcesForPlatform(
+  if (auto fspecs = LocateExecutableScriptingResourcesForPlatform(
           target, module, feedback_stream);
-      !fspecs.IsEmpty())
+      !fspecs.empty())
     return fspecs;
 
   const FileSpec &module_spec = module.GetFileSpec();
   if (!module_spec)
-    return {};
+    return empty;
 
   return LocateExecutableScriptingResourcesFromSafePaths(feedback_stream,
                                                          module_spec, *target);
diff --git a/lldb/unittests/Platform/PlatformDarwinTest.cpp b/lldb/unittests/Platform/PlatformDarwinTest.cpp
index 448dcab7070df..70986bf3e0199 100644
--- a/lldb/unittests/Platform/PlatformDarwinTest.cpp
+++ b/lldb/unittests/Platform/PlatformDarwinTest.cpp
@@ -145,12 +145,11 @@ TEST_F(PlatformDarwinLocateTest,
   CreateFile("TestModule.sh", m_tmp_dsym_python_dir);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 1u);
-  EXPECT_EQ(fspecs.GetFileSpecAtIndex(0).GetFilename(), "TestModule.py");
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 1u);
+  EXPECT_EQ(fspecs.begin()->getFirst().GetFilename(), "TestModule.py");
 }
 
 TEST_F(PlatformDarwinLocateTest,
@@ -171,12 +170,11 @@ TEST_F(PlatformDarwinLocateTest,
   CreateFile("TestModule.sh", m_tmp_dsym_python_dir);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 1u);
-  EXPECT_EQ(fspecs.GetFileSpecAtIndex(0).GetFilename(), "TestModule.py");
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 1u);
+  EXPECT_EQ(fspecs.begin()->getFirst().GetFilename(), "TestModule.py");
 }
 
 TEST_F(PlatformDarwinLocateTest,
@@ -197,11 +195,10 @@ TEST_F(PlatformDarwinLocateTest,
   CreateFile("TestModule.1.py", m_tmp_dsym_python_dir);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 0u);
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 0u);
 }
 
 TEST_F(PlatformDarwinLocateTest,
@@ -228,11 +225,10 @@ TEST_F(PlatformDarwinLocateTest,
   CreateFile("TestModule.py", nested_dir);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 0u);
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 0u);
 }
 
 TEST_F(
@@ -256,12 +252,11 @@ TEST_F(
   CreateFile("TestModule_import.py", m_tmp_dsym_python_dir);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 1u);
-  EXPECT_EQ(fspecs.GetFileSpecAtIndex(0).GetFilename(), "TestModule_import.py");
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 1u);
+  EXPECT_EQ(fspecs.begin()->getFirst().GetFilename(), "TestModule_import.py");
   EXPECT_TRUE(ss.Empty());
 }
 
@@ -285,11 +280,10 @@ TEST_F(PlatformDarwinLocateTest,
   ASSERT_TRUE(script_fspec);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 0u);
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 0u);
 
   std::string expected = llvm::formatv(
       "debug script '{0}' cannot be loaded because 'import.py' "
@@ -321,12 +315,11 @@ TEST_F(PlatformDarwinLocateTest,
   ASSERT_TRUE(orig_fspec);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 1u);
-  EXPECT_EQ(fspecs.GetFileSpecAtIndex(0).GetFilename(), "_import.py");
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 1u);
+  EXPECT_EQ(fspecs.begin()->getFirst().GetFilename(), "_import.py");
 
   std::string expected = llvm::formatv(
       "debug script '{0}' cannot be loaded because 'import.py' "
@@ -356,12 +349,11 @@ TEST_F(
   CreateFile("_import.py", m_tmp_dsym_python_dir);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 1u);
-  EXPECT_EQ(fspecs.GetFileSpecAtIndex(0).GetFilename(), "_import.py");
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 1u);
+  EXPECT_EQ(fspecs.begin()->getFirst().GetFilename(), "_import.py");
   EXPECT_TRUE(ss.GetString().empty());
 }
 
@@ -386,11 +378,10 @@ TEST_F(
   ASSERT_TRUE(script_fspec);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 0u);
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 0u);
 
   std::string expected = llvm::formatv(
       "debug script '{0}' cannot be loaded because 'TestModule-1.1 1.py' "
@@ -423,12 +414,11 @@ TEST_F(
   CreateFile("TestModule_1_1_1.py", m_tmp_dsym_python_dir);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 1u);
-  EXPECT_EQ(fspecs.GetFileSpecAtIndex(0).GetFilename(), "TestModule_1_1_1.py");
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+                        ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.size(), 1u);
+  EXPECT_EQ(fspecs.begin()->getFirst().GetFilename(), "TestModule_1_1_1.py");
 
   std::string expected = llvm::formatv(
       "debug script '{0}' cannot be loaded because"
@@ -458,12 +448,11 @@ TEST_F(
   CreateFile("TestModule_1_1_1.py", m_tmp_dsym_python_dir);
 
   StreamString ss;
-  FileSpecList fspecs =
-      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
-          ->LocateExecutableScriptingResourcesFromDSYM(
-              ss, module_fspec, *m_target_sp, dsym_module_fpec);
-  EXPECT_EQ(fspecs.GetSize(), 1u);
-  EXPECT_EQ(fspecs.GetFileSpecAtIndex(0).GetFilename(), "TestModule_1_1_1.py");
+  auto fspecs = std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+                    ->LocateExecutableScriptingResourcesFromDSYM(
+   ...
[truncated]

Target *target, Module &module, Stream &feedback_stream) {
llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile> file_specs;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

THis change seems awkward. You never accumulate anything into file_specs. When you do return something other than a default constructed object, it's by returning the return of another function bypassing file_specs.
So it seems like directly returning {} makes what you are doing clearer. I don't have to keep checking above "did we set file_specs to anything".

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore this if a future commit starts using file_specs.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SmallDenseMap is a bit awkward in that it doesn't let you just return {}. So I emptied for the dedicated variable.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's unfortunate. If you were intending to only use this for the empty return and not accumulate into it, then naming it something like empty_specs would make the intent clearer. But that's make-work if you are going to end up using it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup makes sense. Renamed it

@jimingham

Copy link
Copy Markdown
Contributor

LGTM

@JDevlieghere JDevlieghere left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM!

This patch changes the `Platform::LocateXXX` to return a map from `FileSpec` to `LoadScriptFromSymFile` enum.

This is needed for llvm#188722, where I intend to set `LoadScriptFromSymFile` per-module.

By default the `Platform::LocateXXX` set the value to whatever the target's current `target.load-script-from-symbol-file` is set to. In llvm#188722 we'll allow overriding this per-target setting on a per-module basis.

Drive-by:
* Added logging when we fail to load a script.
@Michael137
Michael137 force-pushed the lldb/auto-load-style-per-module branch from 291e5b4 to 6752d55 Compare March 31, 2026 22:17
@Michael137
Michael137 enabled auto-merge (squash) March 31, 2026 22:17
@Michael137
Michael137 merged commit 89dec12 into llvm:main Mar 31, 2026
9 of 10 checks passed
@Michael137
Michael137 deleted the lldb/auto-load-style-per-module branch April 1, 2026 06:55
joaovam pushed a commit to joaovam/llvm-project that referenced this pull request Apr 2, 2026
…vm#189696)

This patch changes the `Platform::LocateXXX` to return a map from
`FileSpec` to `LoadScriptFromSymFile` enum.

This is needed for llvm#188722,
where I intend to set `LoadScriptFromSymFile` per-module.

By default the `Platform::LocateXXX` set the value to whatever the
target's current `target.load-script-from-symbol-file` is set to. In
llvm#188722 we'll allow overriding
this per-target setting on a per-module basis.

Drive-by:
* Added logging when we fail to load a script.
Michael137 added a commit that referenced this pull request Apr 7, 2026
…urces can be auto-loaded (#188722)

* Depends on: #189696

This is part of [this
RFC](https://discourse.llvm.org/t/rfc-lldb-moving-libc-data-formatters-out-of-lldb/89591)
which is about turning the libc++ data-formatters into auto-loadable
Python scripts.

Eventually we want the Python data-formatters for `libc++` to be
automatically loaded without requiring user opt-in (since that's how the
builtin formatters have always worked and, in my opinion, we can't
transition to an opt-in model if users have always had the
data-formatters available). To do so we need a way to distinguish which
modules we can *always* auto-load from safe-paths, and which require
`target.load-script-from-symbol-file` to be set to `true`.

This patch adds a setting (`target.auto-load-modules`) that is a
dictionary from module-name to the `LoadScriptFromSymFile` enum,
indicating how the scripts for that module are to be loaded.

Making this a setting also means a user can disable any auto-loading by
clearing it. By default the setting is currently empty. Eventually we'll
want it to contain `libc++.1=true` (and possibly other names which the
`libc++` dylib can commonly have).

**Considerations**:
* I thought about adding an `IsAutoLoadable` API to `FileSpec` and set
it for those that can be auto-loaded. Then we wouldn't have to return
two lists from `LocateExecutableScriptingResources`. I just felt like
`FileSpec` was too high-level of a structure to hold such information so
I opted for the `llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>`.
If people favour one approach over the other, I'm happy to reconsider

**AI Usage**:
* Used Claude to generate the unit-test cases and shell tests. Reviewed
and cleaned them up myself.

---------

Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 7, 2026
…ipting resources can be auto-loaded (#188722)

* Depends on: llvm/llvm-project#189696

This is part of [this
RFC](https://discourse.llvm.org/t/rfc-lldb-moving-libc-data-formatters-out-of-lldb/89591)
which is about turning the libc++ data-formatters into auto-loadable
Python scripts.

Eventually we want the Python data-formatters for `libc++` to be
automatically loaded without requiring user opt-in (since that's how the
builtin formatters have always worked and, in my opinion, we can't
transition to an opt-in model if users have always had the
data-formatters available). To do so we need a way to distinguish which
modules we can *always* auto-load from safe-paths, and which require
`target.load-script-from-symbol-file` to be set to `true`.

This patch adds a setting (`target.auto-load-modules`) that is a
dictionary from module-name to the `LoadScriptFromSymFile` enum,
indicating how the scripts for that module are to be loaded.

Making this a setting also means a user can disable any auto-loading by
clearing it. By default the setting is currently empty. Eventually we'll
want it to contain `libc++.1=true` (and possibly other names which the
`libc++` dylib can commonly have).

**Considerations**:
* I thought about adding an `IsAutoLoadable` API to `FileSpec` and set
it for those that can be auto-loaded. Then we wouldn't have to return
two lists from `LocateExecutableScriptingResources`. I just felt like
`FileSpec` was too high-level of a structure to hold such information so
I opted for the `llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>`.
If people favour one approach over the other, I'm happy to reconsider

**AI Usage**:
* Used Claude to generate the unit-test cases and shell tests. Reviewed
and cleaned them up myself.

---------

Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
Michael137 added a commit to swiftlang/llvm-project that referenced this pull request Apr 8, 2026
…vm#189696)

This patch changes the `Platform::LocateXXX` to return a map from
`FileSpec` to `LoadScriptFromSymFile` enum.

This is needed for llvm#188722,
where I intend to set `LoadScriptFromSymFile` per-module.

By default the `Platform::LocateXXX` set the value to whatever the
target's current `target.load-script-from-symbol-file` is set to. In
llvm#188722 we'll allow overriding
this per-target setting on a per-module basis.

Drive-by:
* Added logging when we fail to load a script.

(cherry picked from commit 89dec12)
Michael137 added a commit to swiftlang/llvm-project that referenced this pull request Apr 8, 2026
…urces can be auto-loaded (llvm#188722)

* Depends on: llvm#189696

This is part of [this
RFC](https://discourse.llvm.org/t/rfc-lldb-moving-libc-data-formatters-out-of-lldb/89591)
which is about turning the libc++ data-formatters into auto-loadable
Python scripts.

Eventually we want the Python data-formatters for `libc++` to be
automatically loaded without requiring user opt-in (since that's how the
builtin formatters have always worked and, in my opinion, we can't
transition to an opt-in model if users have always had the
data-formatters available). To do so we need a way to distinguish which
modules we can *always* auto-load from safe-paths, and which require
`target.load-script-from-symbol-file` to be set to `true`.

This patch adds a setting (`target.auto-load-modules`) that is a
dictionary from module-name to the `LoadScriptFromSymFile` enum,
indicating how the scripts for that module are to be loaded.

Making this a setting also means a user can disable any auto-loading by
clearing it. By default the setting is currently empty. Eventually we'll
want it to contain `libc++.1=true` (and possibly other names which the
`libc++` dylib can commonly have).

**Considerations**:
* I thought about adding an `IsAutoLoadable` API to `FileSpec` and set
it for those that can be auto-loaded. Then we wouldn't have to return
two lists from `LocateExecutableScriptingResources`. I just felt like
`FileSpec` was too high-level of a structure to hold such information so
I opted for the `llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>`.
If people favour one approach over the other, I'm happy to reconsider

**AI Usage**:
* Used Claude to generate the unit-test cases and shell tests. Reviewed
and cleaned them up myself.

---------

Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
(cherry picked from commit e03b731)
cpullvm-upstream-sync Bot pushed a commit to navaneethshan/cpullvm-toolchain-1 that referenced this pull request Apr 13, 2026
…ipting resources can be auto-loaded (#188722)

* Depends on: llvm/llvm-project#189696

This is part of [this
RFC](https://discourse.llvm.org/t/rfc-lldb-moving-libc-data-formatters-out-of-lldb/89591)
which is about turning the libc++ data-formatters into auto-loadable
Python scripts.

Eventually we want the Python data-formatters for `libc++` to be
automatically loaded without requiring user opt-in (since that's how the
builtin formatters have always worked and, in my opinion, we can't
transition to an opt-in model if users have always had the
data-formatters available). To do so we need a way to distinguish which
modules we can *always* auto-load from safe-paths, and which require
`target.load-script-from-symbol-file` to be set to `true`.

This patch adds a setting (`target.auto-load-modules`) that is a
dictionary from module-name to the `LoadScriptFromSymFile` enum,
indicating how the scripts for that module are to be loaded.

Making this a setting also means a user can disable any auto-loading by
clearing it. By default the setting is currently empty. Eventually we'll
want it to contain `libc++.1=true` (and possibly other names which the
`libc++` dylib can commonly have).

**Considerations**:
* I thought about adding an `IsAutoLoadable` API to `FileSpec` and set
it for those that can be auto-loaded. Then we wouldn't have to return
two lists from `LocateExecutableScriptingResources`. I just felt like
`FileSpec` was too high-level of a structure to hold such information so
I opted for the `llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>`.
If people favour one approach over the other, I'm happy to reconsider

**AI Usage**:
* Used Claude to generate the unit-test cases and shell tests. Reviewed
and cleaned them up myself.

---------

Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
YonahGoldberg pushed a commit to YonahGoldberg/llvm-project that referenced this pull request Apr 21, 2026
…urces can be auto-loaded (llvm#188722)

* Depends on: llvm#189696

This is part of [this
RFC](https://discourse.llvm.org/t/rfc-lldb-moving-libc-data-formatters-out-of-lldb/89591)
which is about turning the libc++ data-formatters into auto-loadable
Python scripts.

Eventually we want the Python data-formatters for `libc++` to be
automatically loaded without requiring user opt-in (since that's how the
builtin formatters have always worked and, in my opinion, we can't
transition to an opt-in model if users have always had the
data-formatters available). To do so we need a way to distinguish which
modules we can *always* auto-load from safe-paths, and which require
`target.load-script-from-symbol-file` to be set to `true`.

This patch adds a setting (`target.auto-load-modules`) that is a
dictionary from module-name to the `LoadScriptFromSymFile` enum,
indicating how the scripts for that module are to be loaded.

Making this a setting also means a user can disable any auto-loading by
clearing it. By default the setting is currently empty. Eventually we'll
want it to contain `libc++.1=true` (and possibly other names which the
`libc++` dylib can commonly have).

**Considerations**:
* I thought about adding an `IsAutoLoadable` API to `FileSpec` and set
it for those that can be auto-loaded. Then we wouldn't have to return
two lists from `LocateExecutableScriptingResources`. I just felt like
`FileSpec` was too high-level of a structure to hold such information so
I opted for the `llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>`.
If people favour one approach over the other, I'm happy to reconsider

**AI Usage**:
* Used Claude to generate the unit-test cases and shell tests. Reviewed
and cleaned them up myself.

---------

Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
llvm-upstreamsync Bot pushed a commit to qualcomm/cpullvm-toolchain that referenced this pull request Apr 24, 2026
…ipting resources can be auto-loaded (#188722)

* Depends on: llvm/llvm-project#189696

This is part of [this
RFC](https://discourse.llvm.org/t/rfc-lldb-moving-libc-data-formatters-out-of-lldb/89591)
which is about turning the libc++ data-formatters into auto-loadable
Python scripts.

Eventually we want the Python data-formatters for `libc++` to be
automatically loaded without requiring user opt-in (since that's how the
builtin formatters have always worked and, in my opinion, we can't
transition to an opt-in model if users have always had the
data-formatters available). To do so we need a way to distinguish which
modules we can *always* auto-load from safe-paths, and which require
`target.load-script-from-symbol-file` to be set to `true`.

This patch adds a setting (`target.auto-load-modules`) that is a
dictionary from module-name to the `LoadScriptFromSymFile` enum,
indicating how the scripts for that module are to be loaded.

Making this a setting also means a user can disable any auto-loading by
clearing it. By default the setting is currently empty. Eventually we'll
want it to contain `libc++.1=true` (and possibly other names which the
`libc++` dylib can commonly have).

**Considerations**:
* I thought about adding an `IsAutoLoadable` API to `FileSpec` and set
it for those that can be auto-loaded. Then we wouldn't have to return
two lists from `LocateExecutableScriptingResources`. I just felt like
`FileSpec` was too high-level of a structure to hold such information so
I opted for the `llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>`.
If people favour one approach over the other, I'm happy to reconsider

**AI Usage**:
* Used Claude to generate the unit-test cases and shell tests. Reviewed
and cleaned them up myself.

---------

Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
zwu-2025 pushed a commit to zwu-2025/llvm-project that referenced this pull request May 17, 2026
…vm#189696)

This patch changes the `Platform::LocateXXX` to return a map from
`FileSpec` to `LoadScriptFromSymFile` enum.

This is needed for llvm#188722,
where I intend to set `LoadScriptFromSymFile` per-module.

By default the `Platform::LocateXXX` set the value to whatever the
target's current `target.load-script-from-symbol-file` is set to. In
llvm#188722 we'll allow overriding
this per-target setting on a per-module basis.

Drive-by:
* Added logging when we fail to load a script.
zwu-2025 pushed a commit to zwu-2025/llvm-project that referenced this pull request May 17, 2026
…urces can be auto-loaded (llvm#188722)

* Depends on: llvm#189696

This is part of [this
RFC](https://discourse.llvm.org/t/rfc-lldb-moving-libc-data-formatters-out-of-lldb/89591)
which is about turning the libc++ data-formatters into auto-loadable
Python scripts.

Eventually we want the Python data-formatters for `libc++` to be
automatically loaded without requiring user opt-in (since that's how the
builtin formatters have always worked and, in my opinion, we can't
transition to an opt-in model if users have always had the
data-formatters available). To do so we need a way to distinguish which
modules we can *always* auto-load from safe-paths, and which require
`target.load-script-from-symbol-file` to be set to `true`.

This patch adds a setting (`target.auto-load-modules`) that is a
dictionary from module-name to the `LoadScriptFromSymFile` enum,
indicating how the scripts for that module are to be loaded.

Making this a setting also means a user can disable any auto-loading by
clearing it. By default the setting is currently empty. Eventually we'll
want it to contain `libc++.1=true` (and possibly other names which the
`libc++` dylib can commonly have).

**Considerations**:
* I thought about adding an `IsAutoLoadable` API to `FileSpec` and set
it for those that can be auto-loaded. Then we wouldn't have to return
two lists from `LocateExecutableScriptingResources`. I just felt like
`FileSpec` was too high-level of a structure to hold such information so
I opted for the `llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>`.
If people favour one approach over the other, I'm happy to reconsider

**AI Usage**:
* Used Claude to generate the unit-test cases and shell tests. Reviewed
and cleaned them up myself.

---------

Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
markrvmurray pushed a commit to markrvmurray/llvm-mc6809 that referenced this pull request Jun 14, 2026
…urces can be auto-loaded (#188722)

* Depends on: llvm/llvm-project#189696

This is part of [this
RFC](https://discourse.llvm.org/t/rfc-lldb-moving-libc-data-formatters-out-of-lldb/89591)
which is about turning the libc++ data-formatters into auto-loadable
Python scripts.

Eventually we want the Python data-formatters for `libc++` to be
automatically loaded without requiring user opt-in (since that's how the
builtin formatters have always worked and, in my opinion, we can't
transition to an opt-in model if users have always had the
data-formatters available). To do so we need a way to distinguish which
modules we can *always* auto-load from safe-paths, and which require
`target.load-script-from-symbol-file` to be set to `true`.

This patch adds a setting (`target.auto-load-modules`) that is a
dictionary from module-name to the `LoadScriptFromSymFile` enum,
indicating how the scripts for that module are to be loaded.

Making this a setting also means a user can disable any auto-loading by
clearing it. By default the setting is currently empty. Eventually we'll
want it to contain `libc++.1=true` (and possibly other names which the
`libc++` dylib can commonly have).

**Considerations**:
* I thought about adding an `IsAutoLoadable` API to `FileSpec` and set
it for those that can be auto-loaded. Then we wouldn't have to return
two lists from `LocateExecutableScriptingResources`. I just felt like
`FileSpec` was too high-level of a structure to hold such information so
I opted for the `llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile>`.
If people favour one approach over the other, I'm happy to reconsider

**AI Usage**:
* Used Claude to generate the unit-test cases and shell tests. Reviewed
and cleaned them up myself.

---------

Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants