summaryrefslogtreecommitdiff
path: root/lldb/source/Commands
diff options
context:
space:
mode:
authorMed Ismail Bennani <medismail.bennani@gmail.com>2021-01-08 21:23:34 +0100
committerMed Ismail Bennani <medismail.bennani@gmail.com>2021-01-08 21:23:34 +0100
commit68e63210aeb74d2ef6ef0110da80d1aa78ba4148 (patch)
treef16c4018b1de4df591a2abf66ec44788222166aa /lldb/source/Commands
parent0386f3d4f4183a93d7e029abef8110ae4f148335 (diff)
downloadllvm-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.txt1
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp3
-rw-r--r--lldb/source/Commands/CommandObjectProcessScripted.cpp195
-rw-r--r--lldb/source/Commands/CommandObjectProcessScripted.h24
-rw-r--r--lldb/source/Commands/Options.td6
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.">;