From d62a53aaf1d38a55d1affbd3a30d564a4e9d3171 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Tue, 16 Feb 2021 09:12:41 +0000 Subject: [PATCH] [lldb/Commands] Add command options for ScriptedProcess to ProcessLaunch This patch adds a new command options to the CommandObjectProcessLaunch for scripted processes. Among the options, the user need to specify the class name managing the scripted process. The user can also use a key-value dictionary holding arbitrary data that will be passed to the managing class. This patch also adds getters and setters to `SBLaunchInfo` for the class name managing the scripted process and the dictionary. rdar://65508855 Differential Review: https://reviews.llvm.org/D95710 Signed-off-by: Med Ismail Bennani --- lldb/bindings/interface/SBLaunchInfo.i | 10 ++++ lldb/include/lldb/API/SBLaunchInfo.h | 8 +++ lldb/include/lldb/API/SBStream.h | 1 + lldb/include/lldb/API/SBStructuredData.h | 1 + lldb/include/lldb/Host/ProcessLaunchInfo.h | 28 ++++++++++ lldb/source/API/SBLaunchInfo.cpp | 59 ++++++++++++++++++++++ lldb/source/API/SBTarget.cpp | 1 + lldb/source/Commands/CommandObjectPlatform.cpp | 8 ++- lldb/source/Commands/CommandObjectProcess.cpp | 21 +++++++- .../Commands/CommandOptionsProcessLaunch.cpp | 2 +- lldb/source/Commands/CommandOptionsProcessLaunch.h | 6 +-- lldb/source/Host/common/ProcessLaunchInfo.cpp | 8 ++- 12 files changed, 143 insertions(+), 10 deletions(-) diff --git a/lldb/bindings/interface/SBLaunchInfo.i b/lldb/bindings/interface/SBLaunchInfo.i index d76656d..535ed3b 100644 --- a/lldb/bindings/interface/SBLaunchInfo.i +++ b/lldb/bindings/interface/SBLaunchInfo.i @@ -135,6 +135,16 @@ public: void SetDetachOnError(bool enable); + + const char * + GetScriptedProcessClassName() const; + + void SetScriptedProcessClassName(const char *class_name); + + lldb::SBStructuredData + GetScriptedProcessDictionary() const; + + void SetScriptedProcessDictionary(lldb::SBStructuredData dict); }; } // namespace lldb diff --git a/lldb/include/lldb/API/SBLaunchInfo.h b/lldb/include/lldb/API/SBLaunchInfo.h index 04ebb57..eb4f4a6 100644 --- a/lldb/include/lldb/API/SBLaunchInfo.h +++ b/lldb/include/lldb/API/SBLaunchInfo.h @@ -171,6 +171,14 @@ public: void SetDetachOnError(bool enable); + const char *GetScriptedProcessClassName() const; + + void SetScriptedProcessClassName(const char *class_name); + + lldb::SBStructuredData GetScriptedProcessDictionary() const; + + void SetScriptedProcessDictionary(lldb::SBStructuredData dict); + protected: friend class SBPlatform; friend class SBTarget; diff --git a/lldb/include/lldb/API/SBStream.h b/lldb/include/lldb/API/SBStream.h index f44b87b..f39bf13 100644 --- a/lldb/include/lldb/API/SBStream.h +++ b/lldb/include/lldb/API/SBStream.h @@ -72,6 +72,7 @@ protected: friend class SBFunction; friend class SBInstruction; friend class SBInstructionList; + friend class SBLaunchInfo; friend class SBLineEntry; friend class SBMemoryRegionInfo; friend class SBModule; diff --git a/lldb/include/lldb/API/SBStructuredData.h b/lldb/include/lldb/API/SBStructuredData.h index 44a86bd..07763f2 100644 --- a/lldb/include/lldb/API/SBStructuredData.h +++ b/lldb/include/lldb/API/SBStructuredData.h @@ -88,6 +88,7 @@ public: size_t GetStringValue(char *dst, size_t dst_len) const; protected: + friend class SBLaunchInfo; friend class SBTraceOptions; friend class SBDebugger; friend class SBTarget; diff --git a/lldb/include/lldb/Host/ProcessLaunchInfo.h b/lldb/include/lldb/Host/ProcessLaunchInfo.h index ee97555..8831337 100644 --- a/lldb/include/lldb/Host/ProcessLaunchInfo.h +++ b/lldb/include/lldb/Host/ProcessLaunchInfo.h @@ -20,6 +20,7 @@ #include "lldb/Host/PseudoTerminal.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/ProcessInfo.h" +#include "lldb/Utility/StructuredData.h" namespace lldb_private { @@ -146,6 +147,28 @@ public: return m_flags.Test(lldb::eLaunchFlagDetachOnError); } + bool IsScriptedProcess() const { + return !m_scripted_process_class_name.empty(); + } + + std::string GetScriptedProcessClassName() const { + return m_scripted_process_class_name; + } + + void SetScriptedProcessClassName(std::string name) { + m_scripted_process_class_name = name; + } + + lldb_private::StructuredData::DictionarySP + GetScriptedProcessDictionarySP() const { + return m_scripted_process_dictionary_sp; + } + + void SetScriptedProcessDictionarySP( + lldb_private::StructuredData::DictionarySP dictionary_sp) { + m_scripted_process_dictionary_sp = dictionary_sp; + } + protected: FileSpec m_working_dir; std::string m_plugin_name; @@ -161,6 +184,11 @@ protected: // meaning to the upper levels of lldb. lldb::ListenerSP m_listener_sp; lldb::ListenerSP m_hijack_listener_sp; + std::string m_scripted_process_class_name; // The name of the class that will + // manage a scripted process. + StructuredData::DictionarySP + m_scripted_process_dictionary_sp; // A dictionary that holds key/value + // pairs passed to the scripted process. }; } diff --git a/lldb/source/API/SBLaunchInfo.cpp b/lldb/source/API/SBLaunchInfo.cpp index cda8134..70cd1c6 100644 --- a/lldb/source/API/SBLaunchInfo.cpp +++ b/lldb/source/API/SBLaunchInfo.cpp @@ -10,8 +10,12 @@ #include "SBReproducerPrivate.h" #include "lldb/API/SBEnvironment.h" +#include "lldb/API/SBError.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBListener.h" +#include "lldb/API/SBStream.h" +#include "lldb/API/SBStructuredData.h" +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/Host/ProcessLaunchInfo.h" using namespace lldb; @@ -343,6 +347,53 @@ bool SBLaunchInfo::GetDetachOnError() const { return m_opaque_sp->GetDetachOnError(); } +const char *SBLaunchInfo::GetScriptedProcessClassName() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBLaunchInfo, + GetScriptedProcessClassName); + + // Constify this string so that it is saved in the string pool. Otherwise it + // would be freed when this function goes out of scope. + ConstString class_name(m_opaque_sp->GetScriptedProcessClassName().c_str()); + return class_name.AsCString(); +} + +void SBLaunchInfo::SetScriptedProcessClassName(const char *class_name) { + LLDB_RECORD_METHOD(void, SBLaunchInfo, SetScriptedProcessClassName, + (const char *), class_name); + + m_opaque_sp->SetScriptedProcessClassName(class_name); +} + +lldb::SBStructuredData SBLaunchInfo::GetScriptedProcessDictionary() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBStructuredData, SBLaunchInfo, + GetScriptedProcessDictionary); + + lldb_private::StructuredData::DictionarySP dict_sp = + m_opaque_sp->GetScriptedProcessDictionarySP(); + + SBStructuredData data; + data.m_impl_up->SetObjectSP(dict_sp); + + return LLDB_RECORD_RESULT(data); +} + +void SBLaunchInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) { + LLDB_RECORD_METHOD(void, SBLaunchInfo, SetScriptedProcessDictionary, + (lldb::SBStructuredData), dict); + + SBStream stream; + SBError error = dict.GetAsJSON(stream); + + if (error.Fail()) + return; + + StructuredData::DictionarySP dict_sp; + llvm::json::OStream s(stream.ref().AsRawOstream()); + dict_sp->Serialize(s); + + m_opaque_sp->SetScriptedProcessDictionarySP(dict_sp); +} + namespace lldb_private { namespace repro { @@ -403,6 +454,14 @@ void RegisterMethods(Registry &R) { ()); LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetDetachOnError, (bool)); LLDB_REGISTER_METHOD_CONST(bool, SBLaunchInfo, GetDetachOnError, ()); + LLDB_REGISTER_METHOD_CONST(const char *, SBLaunchInfo, + GetScriptedProcessClassName, ()); + LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetScriptedProcessClassName, + (const char *)); + LLDB_REGISTER_METHOD_CONST(lldb::SBStructuredData, SBLaunchInfo, + GetScriptedProcessDictionary, ()); + LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetScriptedProcessDictionary, + (lldb::SBStructuredData)); LLDB_REGISTER_METHOD(void, SBLaunchInfo, SetEnvironment, (const lldb::SBEnvironment &, bool)); LLDB_REGISTER_METHOD(lldb::SBEnvironment, SBLaunchInfo, GetEnvironment, ()); diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index b376bc4..d5a2354 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -446,6 +446,7 @@ SBProcess SBTarget::Launch(SBLaunchInfo &sb_launch_info, SBError &error) { if (arch_spec.IsValid()) launch_info.GetArchitecture() = arch_spec; + target_sp->SetProcessLaunchInfo(launch_info); error.SetError(target_sp->Launch(launch_info, nullptr)); sb_launch_info.set_ref(launch_info); sb_process.SetSP(target_sp->GetProcessSP()); diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index f306da3..d0c58ac 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -1009,11 +1009,14 @@ public: "Launch a new process on a remote platform.", "platform process launch program", eCommandRequiresTarget | eCommandTryTargetAPILock), - m_options() {} + m_options(), m_all_options() { + m_all_options.Append(&m_options); + m_all_options.Finalize(); + } ~CommandObjectPlatformProcessLaunch() override = default; - Options *GetOptions() override { return &m_options; } + Options *GetOptions() override { return &m_all_options; } protected: bool DoExecute(Args &args, CommandReturnObject &result) override { @@ -1085,6 +1088,7 @@ protected: } CommandOptionsProcessLaunch m_options; + OptionGroupOptions m_all_options; }; // "platform process list" diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index c21c499..06d2f54 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -17,6 +17,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" #include "lldb/Interpreter/Options.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" @@ -108,7 +109,12 @@ public: interpreter, "process launch", "Launch the executable in the debugger.", nullptr, eCommandRequiresTarget, "restart"), - m_options() { + m_options(), m_class_options("scripted process"), m_all_options() { + m_all_options.Append(&m_options); + m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, + LLDB_OPT_SET_1); + m_all_options.Finalize(); + CommandArgumentEntry arg; CommandArgumentData run_args_arg; @@ -135,7 +141,7 @@ public: request, nullptr); } - Options *GetOptions() override { return &m_options; } + Options *GetOptions() override { return &m_all_options; } const char *GetRepeatCommand(Args ¤t_command_args, uint32_t index) override { @@ -180,6 +186,15 @@ protected: disable_aslr = target->GetDisableASLR(); } + if (!m_class_options.GetName().empty()) { + m_options.launch_info.SetProcessPluginName("ScriptedProcess"); + m_options.launch_info.SetScriptedProcessClassName( + m_class_options.GetName()); + m_options.launch_info.SetScriptedProcessDictionarySP( + m_class_options.GetStructuredData()); + target->SetProcessLaunchInfo(m_options.launch_info); + } + if (disable_aslr) m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR); else @@ -253,6 +268,8 @@ protected: } CommandOptionsProcessLaunch m_options; + OptionGroupPythonClassWithDict m_class_options; + OptionGroupOptions m_all_options; }; #define LLDB_OPTIONS_process_attach diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp index dfc4887..a618796 100644 --- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp +++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp @@ -30,7 +30,7 @@ Status CommandOptionsProcessLaunch::SetOptionValue( uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) { Status error; - const int short_option = m_getopt_table[option_idx].val; + const int short_option = g_process_launch_options[option_idx].short_option; switch (short_option) { case 's': // Stop at program entry point diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.h b/lldb/source/Commands/CommandOptionsProcessLaunch.h index e0ece8a..d18a232 100644 --- a/lldb/source/Commands/CommandOptionsProcessLaunch.h +++ b/lldb/source/Commands/CommandOptionsProcessLaunch.h @@ -1,4 +1,4 @@ -//===-- CommandOptionsProcessLaunch.h -------------------------------------===// +//===-- CommandOptionsProcessLaunch.h ---------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -16,9 +16,9 @@ namespace lldb_private { // CommandOptionsProcessLaunch -class CommandOptionsProcessLaunch : public lldb_private::Options { +class CommandOptionsProcessLaunch : public lldb_private::OptionGroup { public: - CommandOptionsProcessLaunch() : lldb_private::Options() { + CommandOptionsProcessLaunch() : lldb_private::OptionGroup() { // Keep default values of all options in one place: OptionParsingStarting // () OptionParsingStarting(nullptr); diff --git a/lldb/source/Host/common/ProcessLaunchInfo.cpp b/lldb/source/Host/common/ProcessLaunchInfo.cpp index 1b4b2c6..d42687e 100644 --- a/lldb/source/Host/common/ProcessLaunchInfo.cpp +++ b/lldb/source/Host/common/ProcessLaunchInfo.cpp @@ -32,7 +32,8 @@ ProcessLaunchInfo::ProcessLaunchInfo() : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0), m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0), m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr), - m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() {} + m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp(), + m_scripted_process_class_name(), m_scripted_process_dictionary_sp() {} ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec, const FileSpec &stdout_file_spec, @@ -42,7 +43,8 @@ ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec, : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags), m_file_actions(), m_pty(new PseudoTerminal), m_resume_count(0), m_monitor_callback(nullptr), m_monitor_callback_baton(nullptr), - m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp() { + m_monitor_signals(false), m_listener_sp(), m_hijack_listener_sp(), + m_scripted_process_class_name(), m_scripted_process_dictionary_sp() { if (stdin_file_spec) { FileAction file_action; const bool read = true; @@ -171,6 +173,8 @@ void ProcessLaunchInfo::Clear() { m_resume_count = 0; m_listener_sp.reset(); m_hijack_listener_sp.reset(); + m_scripted_process_class_name.clear(); + m_scripted_process_dictionary_sp.reset(); } void ProcessLaunchInfo::SetMonitorProcessCallback( -- 2.7.4