[lldb][Module] Only call LoadScriptingResourceInTarget via ModuleList (#190136)

This patch is motivated by
https://github.com/llvm/llvm-project/pull/189943, where we would like to
print the "these module scripts weren't loaded" warning for *all*
modules batched together. I.e., we want to print the warning *after* all
the script loading attempts, not from within each attempt.

To do so we want to hoist the `ReportWarning` calls in
`Module::LoadScriptingResourceInTarget` out into the callsites. But if
we do that, the callers have to remember to print the warnings. To avoid
this, we redirect all callsites to use
`ModuleList::LoadScriptingResourceInTarget`, which will be responsible
for printing the warnings.

To avoid future accidental uses of
`Module::LoadScriptingResourceInTarget` I moved the API into
`ModuleList` and made it `private`.
This commit is contained in:
Michael Buch 2026-04-03 08:03:11 +01:00 committed by GitHub
parent 8db1f6492a
commit f91124a55b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 98 additions and 114 deletions

View File

@ -510,8 +510,6 @@ public:
/// \b true if it is, \b false otherwise.
bool IsLoadedInTarget(Target *target);
bool LoadScriptingResourceInTarget(Target *target, Status &error);
/// Get the number of compile units for this module.
///
/// \return

View File

@ -559,6 +559,11 @@ protected:
/// An orphaned module that lives only in the ModuleList has a count of 1.
static constexpr long kUseCountModuleListOrphaned = 1;
private:
static bool LoadScriptingResourceInTargetForModule(Module &module,
Target &target,
Status &error);
public:
typedef LockingAdaptedIterable<std::recursive_mutex, collection>
ModuleIterable;

View File

@ -4400,16 +4400,10 @@ protected:
// Make sure we load any scripting resources that may be embedded
// in the debug info files in case the platform supports that.
Status error;
module_sp->LoadScriptingResourceInTarget(target, error);
if (error.Fail() && error.AsCString())
result.AppendWarningWithFormat(
"unable to load scripting data for module %s - error "
"reported was %s",
module_sp->GetFileSpec()
.GetFileNameStrippingExtension()
.GetCString(),
error.AsCString());
std::list<Status> errors;
module_list.LoadScriptingResourcesInTarget(target, errors);
for (const auto &err : errors)
result.AppendWarning(err.AsCString());
flush = true;
result.SetStatus(eReturnStatusSuccessFinishResult);

View File

@ -1419,93 +1419,6 @@ bool Module::IsLoadedInTarget(Target *target) {
return false;
}
static bool LoadScriptingModule(const FileSpec &scripting_fspec,
ScriptInterpreter &script_interpreter,
Target &target, Status &error) {
assert(scripting_fspec);
StreamString scripting_stream;
scripting_fspec.Dump(scripting_stream.AsRawOstream());
LoadScriptOptions options;
return script_interpreter.LoadScriptingModule(
scripting_stream.GetData(), options, error,
/*module_sp*/ nullptr, /*extra_path*/ {}, target.shared_from_this());
}
bool Module::LoadScriptingResourceInTarget(Target *target, Status &error) {
Log *log = GetLog(LLDBLog::Modules);
if (!target) {
error = Status::FromErrorString("invalid destination Target");
return false;
}
Debugger &debugger = target->GetDebugger();
const ScriptLanguage script_language = debugger.GetScriptLanguage();
if (script_language == eScriptLanguageNone)
return true;
ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter();
if (!script_interpreter) {
error = Status::FromErrorString("invalid ScriptInterpreter");
return false;
}
PlatformSP platform_sp(target->GetPlatform());
if (!platform_sp) {
error = Status::FromErrorString("invalid Platform");
return false;
}
StreamString 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());
for (const auto &[scripting_fspec, load_style] : file_specs) {
if (load_style == eLoadScriptFromSymFileFalse)
continue;
if (!FileSystem::Instance().Exists(scripting_fspec))
continue;
if (load_style == eLoadScriptFromSymFileWarn) {
// clang-format off
debugger.ReportWarning(
llvm::formatv(
R"('{0}' contains a debug script. To run this script in this debug session:
command script import "{1}"
To run all discovered debug scripts in this session:
settings set target.load-script-from-symbol-file true
)",
GetFileSpec().GetFileNameStrippingExtension(),
scripting_fspec.GetPath()),
debugger.GetID());
// clang-format on
return false;
}
LLDB_LOG(log, "Auto-loading {0}", scripting_fspec.GetPath());
if (!LoadScriptingModule(scripting_fspec, *script_interpreter, *target,
error)) {
LLDB_LOG(log, "Failed to load '{0}'. Remaining scripts won't be loaded.",
scripting_fspec.GetPath());
return false;
}
}
return true;
}
bool Module::SetArchitecture(const ArchSpec &new_arch) {
if (!m_arch.IsValid()) {
m_arch = new_arch;

View File

@ -1332,6 +1332,89 @@ bool ModuleList::RemoveSharedModuleIfOrphaned(const ModuleWP module_wp) {
return GetSharedModuleList().RemoveIfOrphaned(module_wp);
}
static bool LoadScriptingModule(const FileSpec &scripting_fspec,
ScriptInterpreter &script_interpreter,
Target &target, Status &error) {
assert(scripting_fspec);
StreamString scripting_stream;
scripting_fspec.Dump(scripting_stream.AsRawOstream());
LoadScriptOptions options;
return script_interpreter.LoadScriptingModule(
scripting_stream.GetData(), options, error,
/*module_sp*/ nullptr, /*extra_path*/ {}, target.shared_from_this());
}
bool ModuleList::LoadScriptingResourceInTargetForModule(Module &module,
Target &target,
Status &error) {
Log *log = GetLog(LLDBLog::Modules);
Debugger &debugger = target.GetDebugger();
const ScriptLanguage script_language = debugger.GetScriptLanguage();
if (script_language == eScriptLanguageNone)
return true;
ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter();
if (!script_interpreter) {
error = Status::FromErrorString("invalid ScriptInterpreter");
return false;
}
PlatformSP platform_sp = target.GetPlatform();
if (!platform_sp) {
error = Status::FromErrorString("invalid Platform");
return false;
}
StreamString feedback_stream;
llvm::SmallDenseMap<FileSpec, LoadScriptFromSymFile> file_specs =
platform_sp->LocateExecutableScriptingResources(&target, module,
feedback_stream);
if (!feedback_stream.Empty())
debugger.ReportWarning(feedback_stream.GetString().str(), debugger.GetID());
for (const auto &[scripting_fspec, load_style] : file_specs) {
if (load_style == eLoadScriptFromSymFileFalse)
continue;
if (!FileSystem::Instance().Exists(scripting_fspec))
continue;
if (load_style == eLoadScriptFromSymFileWarn) {
// clang-format off
debugger.ReportWarning(
llvm::formatv(
R"('{0}' contains a debug script. To run this script in this debug session:
command script import "{1}"
To run all discovered debug scripts in this session:
settings set target.load-script-from-symbol-file true
)",
module.GetFileSpec().GetFileNameStrippingExtension(),
scripting_fspec.GetPath()),
debugger.GetID());
// clang-format on
return false;
}
LLDB_LOG(log, "Auto-loading {0}", scripting_fspec.GetPath());
if (!LoadScriptingModule(scripting_fspec, *script_interpreter, target,
error)) {
LLDB_LOG(log, "Failed to load '{0}'. Remaining scripts won't be loaded.",
scripting_fspec.GetPath());
return false;
}
}
return true;
}
bool ModuleList::LoadScriptingResourcesInTarget(Target *target,
std::list<Status> &errors,
bool continue_on_error) {
@ -1347,7 +1430,7 @@ bool ModuleList::LoadScriptingResourcesInTarget(Target *target,
for (auto module : tmp_module_list.ModulesNoLocking()) {
if (module) {
Status error;
if (!module->LoadScriptingResourceInTarget(target, error)) {
if (!LoadScriptingResourceInTargetForModule(*module, *target, error)) {
if (error.Fail() && error.AsCString()) {
error = Status::FromErrorStringWithFormat(
"unable to load scripting data for "

View File

@ -1542,19 +1542,6 @@ Module *Target::GetExecutableModulePointer() {
return GetExecutableModule().get();
}
static void LoadScriptingResourceForModule(const ModuleSP &module_sp,
Target *target) {
Status error;
if (module_sp && !module_sp->LoadScriptingResourceInTarget(target, error)) {
if (error.AsCString())
target->GetDebugger().GetAsyncErrorStream()->Printf(
"unable to load scripting data for module %s - error reported was "
"%s\n",
module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
error.AsCString());
}
}
void Target::ClearModules(bool delete_locations) {
ModulesDidUnload(m_images, delete_locations);
m_section_load_history.Clear();
@ -1857,9 +1844,13 @@ void Target::ModulesDidLoad(ModuleList &module_list) {
const size_t num_images = module_list.GetSize();
if (m_valid && num_images) {
std::list<Status> errors;
module_list.LoadScriptingResourcesInTarget(this, errors);
for (const auto &err : errors)
GetDebugger().GetAsyncErrorStream()->PutCString(err.AsCString());
for (size_t idx = 0; idx < num_images; ++idx) {
ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
LoadScriptingResourceForModule(module_sp, this);
LoadTypeSummariesForModule(module_sp);
LoadFormattersForModule(module_sp);
}