diff options
author | rchamala <36907958+rchamala@users.noreply.github.com> | 2025-02-23 00:51:43 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-23 00:51:43 -0800 |
commit | 2ff3b18554b115b17d5085b9a4cd779eeafd278a (patch) | |
tree | 0d1e2a464c7ce490a706420ebe77f4acb2656b15 /lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp | |
parent | 0968df9c3a5562f6a8d9f7948065848f3a273b81 (diff) | |
download | llvm-2ff3b18554b115b17d5085b9a4cd779eeafd278a.zip llvm-2ff3b18554b115b17d5085b9a4cd779eeafd278a.tar.gz llvm-2ff3b18554b115b17d5085b9a4cd779eeafd278a.tar.bz2 |
Allow option to ignore module load errors in ScriptedProcess (#127153)
Current state in scripted process expects [all the
modules](https://github.com/llvm/llvm-project/blob/912b154f3a3f8c3cebf5cc5731fd8b0749762da5/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp#L498)
passed into "get_loaded_images" to load successfully else none of them
load. Even if a module loads fine, [but has already been
appended](https://github.com/llvm/llvm-project/blob/912b154f3a3f8c3cebf5cc5731fd8b0749762da5/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp#L495)
it still fails. This is restrictive and does not help our usecase.
**Usecase**: We have a parent scripted process using coredump +
tombstone.
1) Scripted process uses child elf-core process to read memory dump
2) Uses tombstones to pass thread names and modules.
We do not know whether the modules will be successfully downloaded
before creating the scripted process. We use [python module
callbacks](https://github.com/llvm/llvm-project/blob/a57e58dbfaae0e86eb5cafeddf8b598f14b96e36/lldb/source/Target/Platform.cpp#L1593)
to download a module from symbol server at LLDB load time when the
scripted process is being created. The issue is that if one of the
symbol is not found from the list specified in tombstone, none of the
modules load in scripted process. Even if we ensure symbols are present
in symbol server before creating the scripted process, if the load
address is wrong or if the module is already appended, all module loads
are skipped.
**Solution**: Pass in a custom boolean option arg for every module from
python scripted process plugin which will indicate whether to ignore the
module load error. This will provide the flexibility to user for loading
the successfully fetched modules into target while ignoring the failed
ones
---------
Co-authored-by: rchamala <rachamal@fb.com>
Diffstat (limited to 'lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp index d2111ce..6b371a1 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -25,6 +25,8 @@ #include "lldb/Utility/ScriptedMetadata.h" #include "lldb/Utility/State.h" +#include "Plugins/ObjectFile/Placeholder/ObjectFilePlaceholder.h" + #include <mutex> LLDB_PLUGIN_DEFINE(ScriptedProcess) @@ -165,7 +167,7 @@ Status ScriptedProcess::DoLoadCore() { Status ScriptedProcess::DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) { LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__); - + /* MARK: This doesn't reflect how lldb actually launches a process. In reality, it attaches to debugserver, then resume the process. That's not true in all cases. If debugserver is remote, lldb @@ -444,7 +446,6 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { return error_with_message("Couldn't cast image object into dictionary."); ModuleSpec module_spec; - llvm::StringRef value; bool has_path = dict->HasKey("path"); bool has_uuid = dict->HasKey("uuid"); @@ -453,22 +454,17 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { if (!dict->HasKey("load_addr")) return error_with_message("Dictionary is missing key 'load_addr'"); + llvm::StringRef path = ""; if (has_path) { - dict->GetValueForKeyAsString("path", value); - module_spec.GetFileSpec().SetPath(value); + dict->GetValueForKeyAsString("path", path); + module_spec.GetFileSpec().SetPath(path); } + llvm::StringRef uuid = ""; if (has_uuid) { - dict->GetValueForKeyAsString("uuid", value); - module_spec.GetUUID().SetFromStringRef(value); + dict->GetValueForKeyAsString("uuid", uuid); + module_spec.GetUUID().SetFromStringRef(uuid); } - module_spec.GetArchitecture() = target.GetArchitecture(); - - ModuleSP module_sp = - target.GetOrCreateModule(module_spec, true /* notify */); - - if (!module_sp) - return error_with_message("Couldn't create or get module."); lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; lldb::offset_t slide = LLDB_INVALID_OFFSET; @@ -481,6 +477,27 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { if (slide != LLDB_INVALID_OFFSET) load_addr += slide; + module_spec.GetArchitecture() = target.GetArchitecture(); + + ModuleSP module_sp = + target.GetOrCreateModule(module_spec, true /* notify */); + + bool is_placeholder_module = false; + + if (!module_sp) { + // Create a placeholder module + LLDB_LOGF( + GetLog(LLDBLog::Process), + "ScriptedProcess::%s unable to locate the matching " + "object file path %s, creating a placeholder module at 0x%" PRIx64, + __FUNCTION__, path.str().c_str(), load_addr); + + module_sp = Module::CreateModuleFromObjectFile<ObjectFilePlaceholder>( + module_spec, load_addr, module_spec.GetFileSpec().MemorySize()); + + is_placeholder_module = true; + } + bool changed = false; module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/, changed); @@ -488,16 +505,27 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { if (!changed && !module_sp->GetObjectFile()) return error_with_message("Couldn't set the load address for module."); - dict->GetValueForKeyAsString("path", value); - FileSpec objfile(value); + FileSpec objfile(path); module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename()); + if (is_placeholder_module) { + target.GetImages().AppendIfNeeded(module_sp, true /*notify=*/); + return true; + } + return module_list.AppendIfNeeded(module_sp); }; - if (!loaded_images_sp->ForEach(reload_image)) - return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( - LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error); + size_t loaded_images_size = loaded_images_sp->GetSize(); + bool print_error = true; + for (size_t idx = 0; idx < loaded_images_size; idx++) { + const auto &loaded_image = loaded_images_sp->GetItemAtIndex(idx); + if (!reload_image(loaded_image.get()) && print_error) { + print_error = false; + ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( + LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error); + } + } target.ModulesDidLoad(module_list); |