[Lldb-commits] [lldb] [lldb] Skip symbol-script discovery when autoload is disabled (PR #232691)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Oct 16 05:36:11 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Karim Alweheshy (karim-alweheshy)
<details>
<summary>Changes</summary>
**Why:** With symbol-script autoload disabled, LLDB still discovers scripts and creates a symbol vendor. Adding many libraries therefore pays for debug-info setup to discover scripts it will not run.
**Change:** Check the effective per-module policy before discovery, and query symbol-file trust only when the policy needs it. Module overrides and enabled-autoload behavior stay intact.
**Validation:** Five API tests and 23 autoload shell tests pass. Both new disabled-policy laziness tests fail before this fix. The trusted-signing test skips because its required certificate is unavailable.
<details>
<summary>Prior reviews</summary>
[D132803](https://reviews.llvm.org/D132803) documents the discovery cost. Preserve the module-policy and locator-map contracts from #<!-- -->188722 and #<!-- -->189696, and the prompt/warning behavior discussed in #<!-- -->187027 and #<!-- -->189943.
</details>
Assisted-by: OpenAI Codex
---
Full diff: https://github.com/llvm/llvm-project/pull/232691.diff
3 Files Affected:
- (modified) lldb/include/lldb/Target/Platform.h (+8-7)
- (modified) lldb/source/Core/ModuleList.cpp (+12-5)
- (modified) lldb/test/API/macosx/dsym_modules/TestdSYMModuleInit.py (+57)
``````````diff
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index 4fd8c287104cae..257868edef3964 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -273,6 +273,14 @@ class Platform : public PluginInterface {
virtual Status GetFileWithUUID(const FileSpec &platform_file,
const UUID *uuid_ptr, FileSpec &local_file);
+ /// Return the effective scripting policy for the specified module, using
+ /// its explicit override or the target-wide default. This query does not
+ /// locate symbol files or scripting resources, so callers can honor a
+ /// disabled policy before discovering resources.
+ static LoadScriptFromSymFile
+ GetScriptLoadStyleForModule(const FileSpec &module_fspec,
+ const Target &target);
+
/// Locate the scripting resource given a module specification.
///
/// Returns a map from a located script's \c FileSpec to the
@@ -1125,13 +1133,6 @@ class Platform : public PluginInterface {
const ScriptInterpreter::SanitizedScriptingModuleName &sanitized_name,
const FileSpec &original_fspec, const FileSpec &fspec);
- /// Returns the \c LoadScriptFromSymFile of scripting resource associated
- /// with the specified module \c FileSpec. If the load style wasn't explicitly
- /// set for a module, returns the target-wide default.
- static LoadScriptFromSymFile
- GetScriptLoadStyleForModule(const FileSpec &module_fspec,
- const Target &target);
-
private:
typedef std::function<Status(const ModuleSpec &)> ModuleResolver;
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 9f5614538a9874..e6afa6e5a60500 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -1378,6 +1378,12 @@ bool ModuleList::LoadScriptingResourceInTargetForModule(Module &module,
if (script_language == eScriptLanguageNone)
return true;
+ // Discovering scripts can create the module's symbol vendor. Honor the
+ // effective policy before doing that work, including per-module overrides.
+ if (Platform::GetScriptLoadStyleForModule(module.GetFileSpec(), target) ==
+ eLoadScriptFromSymFileFalse)
+ return true;
+
ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter();
if (!script_interpreter) {
error = Status::FromErrorString("invalid ScriptInterpreter");
@@ -1398,7 +1404,7 @@ bool ModuleList::LoadScriptingResourceInTargetForModule(Module &module,
if (!feedback_stream.Empty())
debugger.ReportWarning(feedback_stream.GetString().str(), debugger.GetID());
- const bool trusted = platform_sp->IsSymbolFileTrusted(module);
+ std::optional<bool> trusted;
for (const auto &[scripting_fspec, load_style] : file_specs) {
if (load_style == eLoadScriptFromSymFileFalse)
@@ -1413,10 +1419,11 @@ bool ModuleList::LoadScriptingResourceInTargetForModule(Module &module,
case eLoadScriptFromSymFileTrue:
break;
case eLoadScriptFromSymFileTrusted:
- if (trusted)
- break;
- LLVM_FALLTHROUGH;
case eLoadScriptFromSymFileWarn:
+ if (!trusted.has_value())
+ trusted = platform_sp->IsSymbolFileTrusted(module);
+ if (load_style == eLoadScriptFromSymFileTrusted && *trusted)
+ break;
debugger.ReportWarning(
llvm::formatv(
// clang-format off
@@ -1430,7 +1437,7 @@ To run all discovered debug scripts in this session:
)",
// clang-format on
module.GetFileSpec().GetFileNameStrippingExtension(),
- trusted ? "a trusted" : "an untrusted",
+ *trusted ? "a trusted" : "an untrusted",
scripting_fspec.GetPath()),
debugger.GetID());
diff --git a/lldb/test/API/macosx/dsym_modules/TestdSYMModuleInit.py b/lldb/test/API/macosx/dsym_modules/TestdSYMModuleInit.py
index c3ced18dcf049b..19024fad8f0f8c 100644
--- a/lldb/test/API/macosx/dsym_modules/TestdSYMModuleInit.py
+++ b/lldb/test/API/macosx/dsym_modules/TestdSYMModuleInit.py
@@ -3,6 +3,7 @@
init in debugger and the init in target routines.
"""
+import json
import os, shutil
import lldb
@@ -35,6 +36,62 @@ def test_add_module(self):
target_2 = self.createTestTarget(file_path=executable_2)
self.check_answers(executable_2, ["2", "2", "has_dsym_2"])
+ @no_debug_info_test
+ def test_disabled_autoload_keeps_symbols_lazy(self):
+ self.check_autoload_policy("false")
+
+ @no_debug_info_test
+ def test_disabled_module_override_keeps_symbols_lazy(self):
+ self.check_autoload_policy("true", "false")
+
+ @no_debug_info_test
+ def test_enabled_module_override_loads_script(self):
+ self.check_autoload_policy("false", "true")
+
+ def check_autoload_policy(self, default_policy, module_policy=None):
+ self.py_name = "has_dsym.py"
+ name = f"has_dsym_1_{default_policy}_{module_policy}"
+ executable = self.build_dsym(name)
+
+ self.runCmd("settings set target.preload-symbols false")
+ self.runCmd(
+ f"settings set target.load-script-from-symbol-file {default_policy}"
+ )
+ if module_policy is not None:
+ self.runCmd(
+ "settings set target.auto-load-scripts-for-modules "
+ f"{name}={module_policy}"
+ )
+ self.interp = self.dbg.GetCommandInterpreter()
+ target = self.createTestTarget(
+ file_path=executable, load_dependent_modules=False
+ )
+
+ if module_policy == "true":
+ self.check_answers(executable, ["1", "1", name])
+ return
+
+ # GetStatistics does not create the symbol file. Inspecting symbols
+ # through SBModule would itself defeat the laziness being tested.
+ stream = lldb.SBStream()
+ target.GetStatistics().GetAsJSON(stream)
+ stats = json.loads(stream.GetData())
+ module = next(m for m in stats["modules"] if m["path"] == executable)
+ self.assertNotIn("symbolFilePath", module)
+ self.assertEqual(module["debugInfoByteSize"], 0)
+
+ # Disabling script autoload must not disable subsequent source lookup.
+ breakpoint = target.BreakpointCreateByLocation(
+ "main.c", line_number("main.c", "Set a breakpoint here")
+ )
+ self.assertEqual(breakpoint.GetNumLocations(), 1)
+ stream = lldb.SBStream()
+ target.GetStatistics().GetAsJSON(stream)
+ stats = json.loads(stream.GetData())
+ module = next(m for m in stats["modules"] if m["path"] == executable)
+ self.assertIn("symbolFilePath", module)
+ self.assertGreater(module["debugInfoByteSize"], 0)
+
def check_answers(self, name, answers):
result = lldb.SBCommandReturnObject()
self.interp.HandleCommand("report_command", result)
``````````
</details>
https://github.com/llvm/llvm-project/pull/232691
More information about the lldb-commits
mailing list