Index: lldb/examples/python/scripted_process/crashlog_scripted_process.py =================================================================== --- lldb/examples/python/scripted_process/crashlog_scripted_process.py +++ lldb/examples/python/scripted_process/crashlog_scripted_process.py @@ -25,18 +25,16 @@ self.extended_thread_info = crash_log.asb def load_images(self, images): - #TODO: Add to self.loaded_images and load images in lldb + self.loaded_images.clear() if images: for image in images: if image not in self.loaded_images: if image.uuid == uuid.UUID(int=0): continue - err = image.add_module(self.target) - if err: - # Append to SBCommandReturnObject - print(err) - else: - self.loaded_images.append(image) + for section in image.section_infos: + if section.start_addr and section.name == "__TEXT": + self.loaded_images.append({"uuid": str(image.uuid), + "load_addr": section.start_addr}) for thread in crash_log.threads: if self.load_all_images: @@ -93,6 +91,7 @@ self.exception = None self.extended_thread_info = None self.parse_crashlog() + self.capabilities['force_symbol_lookup'] = True def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo: return None Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp =================================================================== --- lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -11,7 +11,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" - +#include "lldb/Core/Progress.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -19,12 +19,15 @@ #include "lldb/Interpreter/OptionGroupBoolean.h" #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Interpreter/ScriptedMetadata.h" +#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Queue.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/State.h" +#include "llvm/Support/ThreadPool.h" + #include LLDB_PLUGIN_DEFINE(ScriptedProcess) @@ -383,19 +386,31 @@ return ScriptedInterface::ErrorWithMessage( LLVM_PRETTY_FUNCTION, "No loaded images.", error); + size_t num_images_to_load = loaded_images_sp->GetSize(); ModuleList module_list; Target &target = GetTarget(); - auto reload_image = [&target, &module_list, &error_with_message]( - StructuredData::Object *obj) -> bool { - StructuredData::Dictionary *dict = obj->GetAsDictionary(); - + StructuredData::DictionarySP capabilities_sp = + GetInterface().GetCapabilities(); + if (!capabilities_sp) + ScriptedInterface::ErrorWithMessage( + LLVM_PRETTY_FUNCTION, + "Couldn't fetch scripted process capabilities.\nContinuing loading " + "dynamic libraries.", + error); + + bool force_lookup = false; + capabilities_sp->GetValueForKeyAsBoolean("force_symbol_lookup", force_lookup); + + std::mutex m; + std::vector module_specs(num_images_to_load); + Progress progress("Fetching external dependencies", num_images_to_load); + auto fetch_symbols = + [&error_with_message, &progress, &force_lookup, &m, &module_specs, + &target](StructuredData::Dictionary *dict, size_t index) -> bool { if (!dict) 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"); if (!has_path && !has_uuid) @@ -403,6 +418,8 @@ if (!dict->HasKey("load_addr")) return error_with_message("Dictionary is missing key 'load_addr'"); + ModuleSpec module_spec; + llvm::StringRef value; if (has_path) { dict->GetValueForKeyAsString("path", value); module_spec.GetFileSpec().SetPath(value); @@ -414,12 +431,43 @@ } module_spec.GetArchitecture() = target.GetArchitecture(); + Status error; + bool try_download_object_and_symbols = + Symbols::DownloadObjectAndSymbolFile(module_spec, error, force_lookup); + bool has_download_succeeded = + FileSystem::Instance().Exists(module_spec.GetFileSpec()); + bool try_fetching_symbols = (try_download_object_and_symbols || + error.Success() || has_download_succeeded); + + { + std::lock_guard lock(m); + // We need to increment progress and append the module spec to the vector + // even if symbol fetching failed. + progress.Increment(); + module_specs[index] = module_spec; + } + + if (!try_fetching_symbols) + return error_with_message(error.AsCString()); + + return true; + }; + + auto load_modules = [&target, &module_list, + &error_with_message](StructuredData::Dictionary *dict, + ModuleSpec &module_spec) -> bool { + if (!dict) + return error_with_message("Structured data object is not a dictionary."); + ModuleSP module_sp = - target.GetOrCreateModule(module_spec, true /* notify */); + target.GetOrCreateModule(module_spec, true /*=notify*/); if (!module_sp) return error_with_message("Couldn't create or get module."); + Debugger::ReportSymbolChange(module_spec); + + llvm::StringRef value; lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; lldb::addr_t slide = LLDB_INVALID_OFFSET; dict->GetValueForKeyAsInteger("load_addr", load_addr); @@ -438,16 +486,30 @@ if (!changed && !module_sp->GetObjectFile()) return error_with_message("Couldn't set the load address for module."); - dict->GetValueForKeyAsString("path", value); - FileSpec objfile(value); - module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename()); + if (dict->HasKey("path")) { + dict->GetValueForKeyAsString("path", value); + FileSpec objfile(value); + module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename()); + } return module_list.AppendIfNeeded(module_sp); }; - if (!loaded_images_sp->ForEach(reload_image)) - return ScriptedInterface::ErrorWithMessage( - LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error); + // Share one thread pool across operations to avoid the overhead of + // recreating the threads. + llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool()); + + // Create a task runner that fetches symbols and imports dynamic libraries in + // separate threads. + StructuredData::Dictionary *item = nullptr; + for (size_t i = 0; i < num_images_to_load; i++) + if (loaded_images_sp->GetItemAtIndexAsDictionary(i, item)) + task_group.async(fetch_symbols, item, i); + task_group.wait(); + + for (size_t i = 0; i < num_images_to_load; i++) + if (loaded_images_sp->GetItemAtIndexAsDictionary(i, item)) + load_modules(item, module_specs[i]); target.ModulesDidLoad(module_list);