diff options
author | Med Ismail Bennani <medismail.bennani@gmail.com> | 2021-01-08 21:23:34 +0100 |
---|---|---|
committer | Med Ismail Bennani <medismail.bennani@gmail.com> | 2021-01-08 21:23:34 +0100 |
commit | 68e63210aeb74d2ef6ef0110da80d1aa78ba4148 (patch) | |
tree | f16c4018b1de4df591a2abf66ec44788222166aa /lldb/source/Commands | |
parent | 0386f3d4f4183a93d7e029abef8110ae4f148335 (diff) | |
download | llvm-scripted-process.tar.gz |
[lldb/Target] Add Scripted Processes (WIP)scripted-process
Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
Diffstat (limited to 'lldb/source/Commands')
-rw-r--r-- | lldb/source/Commands/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectProcess.cpp | 3 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectProcessScripted.cpp | 195 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectProcessScripted.h | 24 | ||||
-rw-r--r-- | lldb/source/Commands/Options.td | 6 |
5 files changed, 229 insertions, 0 deletions
diff --git a/lldb/source/Commands/CMakeLists.txt b/lldb/source/Commands/CMakeLists.txt index 4f10516c2f69..135afcb43dfd 100644 --- a/lldb/source/Commands/CMakeLists.txt +++ b/lldb/source/Commands/CMakeLists.txt @@ -20,6 +20,7 @@ add_lldb_library(lldbCommands CommandObjectPlatform.cpp CommandObjectPlugin.cpp CommandObjectProcess.cpp + CommandObjectProcessScripted.cpp CommandObjectQuit.cpp CommandObjectRegexCommand.cpp CommandObjectRegister.cpp diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index 1eef2800ce16..7edf2dcfc3b9 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "CommandObjectProcess.h" +#include "CommandObjectProcessScripted.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointSite.h" @@ -1584,6 +1585,8 @@ CommandObjectMultiwordProcess::CommandObjectMultiwordProcess( CommandObjectSP(new CommandObjectProcessSignal(interpreter))); LoadSubCommand("handle", CommandObjectSP(new CommandObjectProcessHandle(interpreter))); + LoadSubCommand("scripted", CommandObjectSP(new CommandObjectProcessScripted( + interpreter))); LoadSubCommand("status", CommandObjectSP(new CommandObjectProcessStatus(interpreter))); LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt( diff --git a/lldb/source/Commands/CommandObjectProcessScripted.cpp b/lldb/source/Commands/CommandObjectProcessScripted.cpp new file mode 100644 index 000000000000..f2d3250027e9 --- /dev/null +++ b/lldb/source/Commands/CommandObjectProcessScripted.cpp @@ -0,0 +1,195 @@ +//===-- CommandObjectProcessScripted.cpp ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CommandObjectProcessScripted.h" + +#include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" + +using namespace lldb; +using namespace lldb_private; + +// CommandObjectProcessScriptedLoad +#pragma mark CommandObjectProcessScriptedLoad +#define LLDB_OPTIONS_process_scripted_load +#include "CommandOptions.inc" + +class CommandObjectProcessScriptedLoad : public CommandObjectParsed { +private: + class CommandOptions : public OptionGroup { + public: + CommandOptions() : OptionGroup() {} + ~CommandOptions() override = default; + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option = + g_process_scripted_load_options[option_idx].short_option; + + switch (short_option) { + case 'S': + m_module = std::string(option_arg); + break; + default: + llvm_unreachable("Unimplemented option"); + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_module = ""; + } + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::makeArrayRef(g_process_scripted_load_options); + } + + std::string m_module; + }; + + CommandOptions m_options; + OptionGroupPythonClassWithDict m_class_options; + OptionGroupOptions m_all_options; + + Options *GetOptions() override { return &m_all_options; } + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { +#if LLDB_ENABLE_PYTHON + if (m_class_options.GetName().empty()) { + result.AppendErrorWithFormat( + "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (m_options.m_module.empty()) { + result.AppendErrorWithFormat("%s needs a module name (-s argument).\n", + m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); + + if (interpreter && + !interpreter->CheckObjectExists(m_class_options.GetName().c_str())) { + result.AppendWarning( + "The provided class does not exist - please define it " + "before attempting to use this frame recognizer"); + } + + Target &target = GetSelectedOrDummyTarget(); + if (target.IsValid()) { + FileSpec script_spec(m_options.m_module); + ScriptedProcessLaunchInfo launch_info = + (m_class_options.IsClass()) + ? ScriptedProcessLaunchInfo(script_spec, + m_class_options.GetName()) + : ScriptedProcessLaunchInfo(m_class_options.GetStructuredData()); + target.SetScriptedProcessLaunchInfo(launch_info); + } +#endif + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } + +public: + CommandObjectProcessScriptedLoad(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "process scripted load", + "Load a scripted process.\n" + "You can either specify a script file and the implementation class " + "or you can specify a dictionary of key (-k) and value (-v) pairs " + "that will be used to populate an SBStructuredData Dictionary, " + "which " + "will be passed to the constructor of the class implementing the " + "scripted step. See the Python Reference for more details.", + nullptr), + m_options(), m_class_options("process scripted load") { + m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, + LLDB_OPT_SET_ALL); + m_all_options.Append(&m_options, LLDB_OPT_SET_3 | LLDB_OPT_SET_4, + LLDB_OPT_SET_ALL); + m_all_options.Finalize(); + /* FIXME: Update Long Help + // SetHelpLong(R"( + // Frame recognizers allow for retrieving information about + // special frames based on ABI, arguments or other special + // properties of that frame, even without source code or + // debug info. Currently, one use case is to extract function + // arguments that would otherwise be unaccesible, or augment + // existing arguments. + // + // Adding a custom frame recognizer is possible by + // implementing a Python class and using the 'frame + // recognizer add' command. The Python class should have a + // 'get_recognized_arguments' method and it will receive an + // argument of type lldb.SBFrame representing the current + // frame that we are trying to recognize. The method should + // return a (possibly empty) list of lldb.SBValue objects + // that represent the recognized arguments. + // + // An example of a recognizer that retrieves the file + // descriptor values from libc functions 'read', 'write' and + // 'close' follows: + // + // class LibcFdRecognizer(object): + // def get_recognized_arguments(self, frame): + // if frame.name in ["read", "write", "close"]: + // fd = frame.EvaluateExpression("$arg1").unsigned + // value = lldb.target.CreateValueFromExpression("fd", + // "(int)%d" % fd) return [value] return [] + // + // The file containing this implementation can be imported + // via 'command script import' and then we can register this + // recognizer with 'frame recognizer add'. It's important to + // restrict the recognizer to the libc library (which is + // libsystem_kernel.dylib on macOS) to avoid matching + // functions with the same name in other modules: + // + // (lldb) command script import .../fd_recognizer.py + // (lldb) frame recognizer add -l + // fd_recognizer.LibcFdRecognizer -n read -s + // libsystem_kernel.dylib + // + // When the program is stopped at the beginning of the 'read' + // function in libc, we can view the recognizer arguments in + // 'frame variable': + // + // (lldb) b read + // (lldb) r + // Process 1234 stopped + // * thread #1, queue = 'com.apple.main-thread', stop reason + // = breakpoint 1.3 frame #0: 0x00007fff06013ca0 + // libsystem_kernel.dylib`read (lldb) frame variable (int) fd + // = 3 + // + // )"); + */ + } + ~CommandObjectProcessScriptedLoad() override = default; +}; + +CommandObjectProcessScripted::CommandObjectProcessScripted( + CommandInterpreter &interpreter) + : CommandObjectMultiword( + interpreter, "process scripted", + "Commands for operating on scripted processes.", + "process plugin <subcommand> [<subcommand-options>]") { + LoadSubCommand("load", CommandObjectSP(new CommandObjectProcessScriptedLoad( + interpreter))); + // TODO: Implement CommandObjectProcessPluginScriptedGenerate + // LoadSubCommand( + // "generate", + // CommandObjectSP(new CommandObjectProcessScriptedLoad(interpreter))); +} diff --git a/lldb/source/Commands/CommandObjectProcessScripted.h b/lldb/source/Commands/CommandObjectProcessScripted.h new file mode 100644 index 000000000000..1472a68ce7b9 --- /dev/null +++ b/lldb/source/Commands/CommandObjectProcessScripted.h @@ -0,0 +1,24 @@ +//===-- CommandObjectProcessScripted.h ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_COMMAND_OBJECT_PROCESS_SCRIPTED_H +#define LLDB_SOURCE_COMMAND_OBJECT_PROCESS_SCRIPTED_H + +#include "lldb/Interpreter/CommandObjectMultiword.h" + +namespace lldb_private { + +class CommandObjectProcessScripted : public CommandObjectMultiword { +public: + CommandObjectProcessScripted(CommandInterpreter &interpreter); + ~CommandObjectProcessScripted() override {} +}; + +}; // namespace lldb_private + +#endif // LLDB_SOURCE_COMMAND_OBJECT_PROCESS_SCRIPTED_H diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 7522f47ca57d..96c5bd6271f9 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -694,6 +694,12 @@ let Command = "process handle" in { Desc<"Whether or not the signal should be passed to the process.">; } +let Command = "process scripted load" in { + def scripted_process_shlib : Option<"shlib", "S">, Arg<"ShlibName">, + Completion<"Module">, + Desc<"Name of the Python module that holds the scripted porcess.">; +} + let Command = "process status" in { def process_status_verbose : Option<"verbose", "v">, Group<1>, Desc<"Show verbose process status including extended crash information.">; |