https://github.com/da-viper updated https://github.com/llvm/llvm-project/pull/143126
>From 95c61d6a917060d7b3a2bc554575eb6a1086ed6e Mon Sep 17 00:00:00 2001 From: Ebuka Ezike <yerimy...@gmail.com> Date: Fri, 6 Jun 2025 13:15:41 +0100 Subject: [PATCH 1/2] [lldb] add plugin names to process save-core error output. --- lldb/include/lldb/Core/PluginManager.h | 2 ++ lldb/source/Core/PluginManager.cpp | 10 ++++++++++ lldb/source/Symbol/SaveCoreOptions.cpp | 22 ++++++++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h index e2f709ecd2ff7..7996dc3fdf3f3 100644 --- a/lldb/include/lldb/Core/PluginManager.h +++ b/lldb/include/lldb/Core/PluginManager.h @@ -212,6 +212,8 @@ class PluginManager { static Status SaveCore(const lldb::ProcessSP &process_sp, lldb_private::SaveCoreOptions &core_options); + static llvm::SmallVector<llvm::StringRef> GetSaveCorePluginNames(); + // ObjectContainer static bool RegisterPlugin( llvm::StringRef name, llvm::StringRef description, diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp index de815e6308838..d02e3030081dc 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -800,6 +800,16 @@ Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp, return error; } +llvm::SmallVector<llvm::StringRef> PluginManager::GetSaveCorePluginNames() { + llvm::SmallVector<llvm::StringRef> plugin_names; + auto instances = GetObjectFileInstances().GetSnapshot(); + for (auto &instance : instances) { + if (instance.save_core) + plugin_names.emplace_back(instance.name); + } + return plugin_names; +} + #pragma mark ObjectContainer struct ObjectContainerInstance diff --git a/lldb/source/Symbol/SaveCoreOptions.cpp b/lldb/source/Symbol/SaveCoreOptions.cpp index d884b00a47b00..c1c85571c8a78 100644 --- a/lldb/source/Symbol/SaveCoreOptions.cpp +++ b/lldb/source/Symbol/SaveCoreOptions.cpp @@ -22,8 +22,26 @@ Status SaveCoreOptions::SetPluginName(const char *name) { } if (!PluginManager::IsRegisteredObjectFilePluginName(name)) { - return Status::FromErrorStringWithFormat( - "plugin name '%s' is not a valid ObjectFile plugin name", name); + StreamString stream; + stream.Printf("plugin name '%s' is not a valid ObjectFile plugin name.", + name); + + llvm::SmallVector<llvm::StringRef> plugin_names = + PluginManager::GetSaveCorePluginNames(); + if (!plugin_names.empty()) { + stream.PutCString(" valid values are: "); + bool is_first = true; + for (llvm::StringRef plugin_name : plugin_names) { + llvm::StringRef delimiter = ", "; + if (is_first) { + delimiter = ""; + is_first = false; + } + stream.Printf("%s\"%s\"", delimiter.data(), plugin_name.data()); + } + stream.PutChar('.'); + } + return Status(stream.GetString().str()); } m_plugin_name = name; >From de106f4b8d350c8ffb8a2b40906a1ce72df3e9a1 Mon Sep 17 00:00:00 2001 From: Ebuka Ezike <yerimy...@gmail.com> Date: Sun, 8 Jun 2025 19:33:01 +0100 Subject: [PATCH 2/2] add help and completion --- .../lldb/Interpreter/CommandCompletions.h | 4 ++++ .../Interpreter/CommandOptionArgumentTable.h | 3 +++ lldb/include/lldb/lldb-enumerations.h | 4 +++- lldb/source/Commands/CommandCompletions.cpp | 12 ++++++++++ lldb/source/Commands/CommandObjectProcess.cpp | 23 ++++++++++++++++++- lldb/source/Commands/Options.td | 3 ++- lldb/source/Core/PluginManager.cpp | 6 +++++ lldb/source/Symbol/SaveCoreOptions.cpp | 13 +++-------- 8 files changed, 55 insertions(+), 13 deletions(-) diff --git a/lldb/include/lldb/Interpreter/CommandCompletions.h b/lldb/include/lldb/Interpreter/CommandCompletions.h index c7292b3b1471a..354debbc7d7bf 100644 --- a/lldb/include/lldb/Interpreter/CommandCompletions.h +++ b/lldb/include/lldb/Interpreter/CommandCompletions.h @@ -97,6 +97,10 @@ class CommandCompletions { static void ProcessNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher); + static void ProcessSaveCorePluginNames(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher); + static void DisassemblyFlavors(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher); diff --git a/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h b/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h index 1875ff6a048d4..d22e3842214dd 100644 --- a/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h +++ b/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h @@ -198,6 +198,8 @@ static constexpr OptionEnumValueElement g_completion_type[] = { "Completes to a type category name."}, {lldb::eCustomCompletion, "custom", "Custom completion."}, {lldb::eThreadIDCompletion, "thread-id", "Completes to a thread ID."}, + {lldb::eProcessSaveCorePluginCompletion, "plugin-name", + "Completes to a process save-core plugin"}, }; llvm::StringRef RegisterNameHelpTextCallback(); @@ -314,6 +316,7 @@ static constexpr CommandObject::ArgumentTableEntry g_argument_table[] = { { lldb::eArgTypeModule, "module", lldb::CompletionType::eModuleCompletion, {}, { nullptr, false }, "The name of a module loaded into the current target." }, { lldb::eArgTypeCPUName, "cpu-name", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The name of a CPU." }, { lldb::eArgTypeCPUFeatures, "cpu-features", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The CPU feature string." }, + { lldb::eArgTypeSaveCorePlugin, "plugin-name", lldb::CompletionType::eProcessSaveCorePluginCompletion, {}, { nullptr, false }, nullptr }, // clang-format on }; diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 6d10cc8bcffcb..144d62181e89b 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -663,6 +663,7 @@ enum CommandArgumentType { eArgTypeModule, eArgTypeCPUName, eArgTypeCPUFeatures, + eArgTypeSaveCorePlugin, eArgTypeLastArg // Always keep this entry as the last entry in this // enumeration!! }; @@ -1319,10 +1320,11 @@ enum CompletionType { eTypeCategoryNameCompletion = (1ul << 24), eCustomCompletion = (1ul << 25), eThreadIDCompletion = (1ul << 26), + eProcessSaveCorePluginCompletion = (1ul << 27), // This last enum element is just for input validation. // Add new completions before this element, // and then increment eTerminatorCompletion's shift value - eTerminatorCompletion = (1ul << 27) + eTerminatorCompletion = (1ul << 28) }; /// Specifies if children need to be re-computed diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp index 38231a8e993c7..a716ba79b4583 100644 --- a/lldb/source/Commands/CommandCompletions.cpp +++ b/lldb/source/Commands/CommandCompletions.cpp @@ -87,6 +87,8 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks( {lldb::eTypeCategoryNameCompletion, CommandCompletions::TypeCategoryNames}, {lldb::eThreadIDCompletion, CommandCompletions::ThreadIDs}, + {lldb::eProcessSaveCorePluginCompletion, + CommandCompletions::ProcessSaveCorePluginNames}, {lldb::eTerminatorCompletion, nullptr} // This one has to be last in the list. }; @@ -736,6 +738,16 @@ void CommandCompletions::ProcessNames(CommandInterpreter &interpreter, for (const ProcessInstanceInfo &info : process_infos) request.TryCompleteCurrentArg(info.GetNameAsStringRef()); } +void CommandCompletions::ProcessSaveCorePluginNames( + CommandInterpreter &interpreter, CompletionRequest &request, + SearchFilter *searcher) { + + const llvm::StringRef prefix = request.GetCursorArgumentPrefix(); + for (llvm::StringRef name : PluginManager::GetSaveCorePluginNames()) { + if (name.starts_with_insensitive(prefix)) + request.AddCompletion(name); + } +} void CommandCompletions::TypeLanguages(CommandInterpreter &interpreter, CompletionRequest &request, diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index b1f243c9e2777..6ac122f9d6b71 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -1281,7 +1281,26 @@ class CommandObjectProcessSaveCore : public CommandObjectParsed { ~CommandOptions() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::ArrayRef(g_process_save_core_options); + if (m_opt_def.empty()) { + auto orig = llvm::ArrayRef(g_process_save_core_options); + m_opt_def.resize(orig.size()); + llvm::copy(g_process_save_core_options, m_opt_def.data()); + for (OptionDefinition &value : m_opt_def) { + llvm::StringRef opt_name = value.long_option; + if (opt_name != "plugin-name") + continue; + + llvm::SmallVector<llvm::StringRef> plugin_names = + PluginManager::GetSaveCorePluginNames(); + m_plugin_enums.resize(plugin_names.size()); + for (auto [num, val] : llvm::zip(plugin_names, m_plugin_enums)) { + val.string_value = num.data(); + } + value.enum_values = llvm::ArrayRef(m_plugin_enums); + break; + } + } + return llvm::ArrayRef(m_opt_def); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, @@ -1312,6 +1331,8 @@ class CommandObjectProcessSaveCore : public CommandObjectParsed { // Instance variables to hold the values for command options. SaveCoreOptions m_core_dump_options; + llvm::SmallVector<OptionEnumValueElement> m_plugin_enums; + std::vector<OptionDefinition> m_opt_def; }; protected: diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 848d42daeb2ad..0077396df0899 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -797,7 +797,8 @@ let Command = "process save_core" in { EnumArg<"SaveCoreStyle">, Desc<"Request a specific style " "of corefile to be saved.">; def process_save_core_plugin_name : Option<"plugin-name", "p">, - OptionalArg<"Plugin">, Desc<"Specify a plugin name to create the core file. " + Arg<"Plugin">, Completion<"ProcessSaveCorePlugin">, + Desc<"Specify a plugin name to create the core file. " "This allows core files to be saved in different formats.">; } diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp index d02e3030081dc..5c0440ed4bb7f 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -792,6 +792,12 @@ Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp, } } + // report for one plugin if a name is specified. + if (error.Success() && !plugin_name.empty()) + error = Status::FromErrorStringWithFormatv( + "\"{}\" plugin is not able to save a core for this process.", + plugin_name); + // Check to see if any of the object file plugins tried and failed to save. // If none ran, set the error message. if (error.Success()) diff --git a/lldb/source/Symbol/SaveCoreOptions.cpp b/lldb/source/Symbol/SaveCoreOptions.cpp index c1c85571c8a78..2bcf2c2e7048c 100644 --- a/lldb/source/Symbol/SaveCoreOptions.cpp +++ b/lldb/source/Symbol/SaveCoreOptions.cpp @@ -29,16 +29,9 @@ Status SaveCoreOptions::SetPluginName(const char *name) { llvm::SmallVector<llvm::StringRef> plugin_names = PluginManager::GetSaveCorePluginNames(); if (!plugin_names.empty()) { - stream.PutCString(" valid values are: "); - bool is_first = true; - for (llvm::StringRef plugin_name : plugin_names) { - llvm::StringRef delimiter = ", "; - if (is_first) { - delimiter = ""; - is_first = false; - } - stream.Printf("%s\"%s\"", delimiter.data(), plugin_name.data()); - } + stream.PutCString(" Valid values are: "); + std::string plugin_names_str = llvm::join(plugin_names, ", "); + stream.PutCString(plugin_names_str); stream.PutChar('.'); } return Status(stream.GetString().str()); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits