summaryrefslogtreecommitdiff
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
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>
-rw-r--r--lldb/bindings/python/python-scripted-process.swig53
-rw-r--r--lldb/bindings/python/python.swig1
-rw-r--r--lldb/examples/python/scripted_process.py43
-rw-r--r--lldb/include/lldb/Host/ProcessLaunchInfo.h29
-rw-r--r--lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h2
-rw-r--r--lldb/include/lldb/Interpreter/ScriptInterpreter.h54
-rw-r--r--lldb/include/lldb/Target/ScriptedProcess.h105
-rw-r--r--lldb/include/lldb/Target/Target.h17
-rw-r--r--lldb/include/lldb/lldb-forward.h1
-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
-rw-r--r--lldb/source/Plugins/Process/Scripted/CMakeLists.txt21
-rw-r--r--lldb/source/Plugins/Process/Scripted/ScriptedProcessOptions.td7
-rw-r--r--lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp2
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp192
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h38
-rw-r--r--lldb/source/Target/CMakeLists.txt3
-rw-r--r--lldb/source/Target/ScriptedProcess.cpp286
-rw-r--r--lldb/source/Target/Target.cpp2
22 files changed, 1082 insertions, 3 deletions
diff --git a/lldb/bindings/python/python-scripted-process.swig b/lldb/bindings/python/python-scripted-process.swig
new file mode 100644
index 000000000000..4b6888f86b77
--- /dev/null
+++ b/lldb/bindings/python/python-scripted-process.swig
@@ -0,0 +1,53 @@
+%pythoncode %{
+from abc import ABC, abstractmethod
+from typing import List
+
+import lldb
+
+class ScriptedProcess(ABC):
+ @abstractmethod
+ def __init__(self):
+ pass
+
+ # Optional initializer
+ def __init__(self, dictionary: lldb.SBStructuredData):
+ pass
+
+ ### Main funcitonnalities
+ @abstractmethod
+ def get_num_memory_regions(self) -> int:
+ pass
+
+ @abstractmethod
+ def get_memory_region_at_index(self, idx: int) -> lldb.SBMemoryRegionInfo:
+ pass
+
+ @abstractmethod
+ def get_num_threads(self):
+ pass
+
+ @abstractmethod
+ def get_thread_at_index(self, idx: int) -> lldb.SBThread:
+ pass
+
+ @abstractmethod
+ def get_register_for_thread(self, tid:int):
+ pass
+
+ @abstractmethod
+ def read_memory_at_address(self, addr:int) -> lldb.SBData:
+ pass
+
+ @abstractmethod
+ def get_loaded_images(self) -> List[str]: # -> List[lldb.SBModule]:
+ pass
+
+ ### Process state
+ @abstractmethod
+ def can_debug(self) -> bool:
+ pass
+
+ @abstractmethod
+ def is_alive(self) -> bool:
+ pass
+%}
diff --git a/lldb/bindings/python/python.swig b/lldb/bindings/python/python.swig
index 66a75328d1e7..9459c8c7be2e 100644
--- a/lldb/bindings/python/python.swig
+++ b/lldb/bindings/python/python.swig
@@ -126,6 +126,7 @@ using namespace lldb;
%include "interfaces.swig"
%include "python-extensions.swig"
%include "python-wrapper.swig"
+%include "python-scripted-process.swig"
%pythoncode%{
_initialize = True
diff --git a/lldb/examples/python/scripted_process.py b/lldb/examples/python/scripted_process.py
new file mode 100644
index 000000000000..b7c43b63de32
--- /dev/null
+++ b/lldb/examples/python/scripted_process.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+
+from lldb import ScriptedProcess
+
+class ScriptedMachCoreProcess(ScriptedProcess):
+ def __init__(self, target: lldb.SBTarget):
+ self.memory_regions = []
+ self.threads = []
+ self.loaded_images = []
+ self.stops = []
+ self.target = target
+
+ def __init__(self, dictionary: lldb.SBStructuredData):
+ # User-defined
+ pass
+
+ ### Main functionalities
+ def get_num_memory_regions(self) -> int:
+ return len(self.memory_region)
+ def get_memory_region_at_index(self, idx: int) -> lldb.SBMemoryRegionInfos:
+ return self.memory_region[idx]
+ def get_num_threads(self) -> int:
+ return len(self.threads)
+ def get_thread_at_index(self, idx: int) -> lldb.SBThread:
+ return self.threads[idx]
+ def get_register_for_thread(self, tid: int):
+ # Follow register data structure used in OS Plugins.
+ return reg
+ def read_memory_at_address(self, addr: int) -> lldb.SBData:
+ # dict[addr:data] ?
+ return addr
+ def get_loaded_images(self) -> list[str]:
+ return self.loaded_images
+
+ ### Process state
+ def can_debug(self) -> bool:
+ return True
+ def is_alive(self) -> bool:
+ return True
+
+example = ScriptedMachCoreProcess("lol")
+print(example.sb_target)
+print(example.get_num_threads())
diff --git a/lldb/include/lldb/Host/ProcessLaunchInfo.h b/lldb/include/lldb/Host/ProcessLaunchInfo.h
index ee9755580825..f12afbbe412a 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 {
@@ -162,6 +163,34 @@ protected:
lldb::ListenerSP m_listener_sp;
lldb::ListenerSP m_hijack_listener_sp;
};
+
+// ScriptedProcessLaunchInfo
+//
+// Describes any information that is required to launch a scripted process
+// - Script file + Class name
+// - Key-Value dictionary
+
+class ScriptedProcessLaunchInfo {
+public:
+ ScriptedProcessLaunchInfo(const FileSpec &script, llvm::StringRef class_name)
+ : m_script_file(script), m_class_name(class_name), m_is_class(true),
+ m_dictionary_sp(nullptr) {}
+
+ ScriptedProcessLaunchInfo(const StructuredData::DictionarySP dictionary)
+ : m_script_file(), m_class_name(), m_is_class(false),
+ m_dictionary_sp(dictionary) {}
+
+ FileSpec GetScriptFileSpec() const { return m_script_file; }
+ llvm::StringRef GetClassName() const { return m_class_name; }
+ bool IsClass() const { return m_is_class; }
+ StructuredData::DictionarySP GetDictionary() const { return m_dictionary_sp; }
+
+private:
+ FileSpec m_script_file;
+ llvm::StringRef m_class_name;
+ bool m_is_class;
+ StructuredData::DictionarySP m_dictionary_sp;
+};
}
#endif // LLDB_HOST_PROCESSLAUNCHINFO_H
diff --git a/lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h b/lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h
index d4c924a44157..f1370179ace9 100644
--- a/lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h
+++ b/lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h
@@ -49,6 +49,8 @@ public:
return m_name;
}
+ bool IsClass() const { return m_is_class; }
+
protected:
std::string m_name;
std::string m_current_key;
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 4abd1ca68167..6746d4f6a109 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -528,6 +528,60 @@ public:
lldb::ScriptLanguage GetLanguage() { return m_script_lang; }
+#pragma mark ScriptedProcessInterface
+
+ virtual StructuredData::DictionarySP
+ ScriptedProcess_Create(StructuredData::ObjectSP scripted_process_object_sp,
+ lldb::pid_t pid, lldb::addr_t context) {
+ return nullptr;
+ }
+
+ virtual StructuredData::DictionarySP ScriptedProcess_GetNumMemoryRegions(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+ }
+
+ virtual lldb::MemoryRegionInfoSP ScriptedProcess_GetMemoryRegionAtIndex(
+ StructuredData::ObjectSP scripted_process_object_sp, size_t index) {
+ return nullptr;
+ }
+
+ virtual StructuredData::DictionarySP ScriptedProcess_GetNumThreads(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+ }
+
+ virtual StructuredData::DictionarySP ScriptedProcess_GetThreadAtIndex(
+ StructuredData::ObjectSP scripted_process_object_sp, size_t index) {
+ return nullptr;
+ }
+
+ virtual StructuredData::DictionarySP ScriptedProcess_GetRegisterForThread(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+ }
+
+ virtual StructuredData::DictionarySP ScriptedProcess_ReadMemoryAtAddress(
+ StructuredData::ObjectSP scripted_process_object_sp, lldb::addr_t address,
+ size_t size) {
+ return nullptr;
+ }
+
+ virtual StructuredData::DictionarySP ScriptedProcess_GetLoadedImages(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+ }
+
+ virtual StructuredData::DictionarySP ScriptedProcess_CanDebug(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+ }
+
+ virtual StructuredData::DictionarySP
+ ScriptedProcess_IsAlive(StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+ }
+
protected:
Debugger &m_debugger;
lldb::ScriptLanguage m_script_lang;
diff --git a/lldb/include/lldb/Target/ScriptedProcess.h b/lldb/include/lldb/Target/ScriptedProcess.h
new file mode 100644
index 000000000000..2e2ac4fab70f
--- /dev/null
+++ b/lldb/include/lldb/Target/ScriptedProcess.h
@@ -0,0 +1,105 @@
+//===-- ScriptableProcess.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_SCRIPTABLE_PROCESS_H
+#define LLDB_SOURCE_PLUGINS_SCRIPTABLE_PROCESS_H
+
+#include "lldb/Target/Process.h"
+//#include "lldb/Target/StopInfo.h"
+//#include "lldb/Target/Target.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Status.h"
+//
+//#include "llvm/Support/Format.h"
+//#include "llvm/Support/raw_ostream.h"
+
+namespace lldb_private {
+
+class ScriptedProcess : public Process {
+public:
+ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *crash_file_path,
+ bool can_connect);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+ const ScriptedProcessLaunchInfo &launch_info);
+
+ ~ScriptedProcess() override;
+
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
+
+ DynamicLoader *GetDynamicLoader() override { return nullptr; }
+
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ SystemRuntime *GetSystemRuntime() override { return nullptr; }
+
+ Status DoDestroy() override;
+
+ void RefreshStateAfterStop() override;
+
+ bool IsAlive() override;
+
+ bool WarnBeforeDetach() const override;
+
+ size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) override;
+
+ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) override;
+
+ ArchSpec GetArchitecture();
+
+ Status GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info) override;
+
+ Status
+ GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list) override;
+
+ bool GetProcessInfo(ProcessInstanceInfo &info) override;
+
+ Status WillResume() override {
+ Status error;
+ error.SetErrorStringWithFormat(
+ "error: %s does not support resuming processes",
+ GetPluginName().GetCString());
+ return error;
+ }
+
+protected:
+ void Clear();
+
+ bool UpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) override;
+
+private:
+ const ScriptedProcessLaunchInfo &m_launch_info;
+ lldb::ScriptInterpreterSP m_interpreter_sp;
+ lldb_private::StructuredData::ObjectSP m_python_object_sp;
+ // lldb::DataBufferSP m_core_data;
+ // llvm::ArrayRef<minidump::Thread> m_thread_list;
+ // const minidump::ExceptionStream *m_active_exception;
+ // bool m_is_wow64;
+ // llvm::Optional<MemoryRegionInfos> m_memory_regions;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_SCRIPTABLE_PROCESS_H
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 69baefb964b0..af0ab6b1be83 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -519,6 +519,20 @@ public:
bool IsDummyTarget() const { return m_is_dummy_target; }
+ bool IsScriptable() const {
+ return m_scripted_process_launch_info.hasValue();
+ }
+
+ llvm::Optional<lldb_private::ScriptedProcessLaunchInfo>
+ GetScriptedProcessLaunchInfo() const {
+ return m_scripted_process_launch_info;
+ }
+
+ void
+ SetScriptedProcessLaunchInfo(const ScriptedProcessLaunchInfo &launch_info) {
+ m_scripted_process_launch_info = launch_info;
+ }
+
/// Find a binary on the system and return its Module,
/// or return an existing Module that is already in the Target.
///
@@ -1420,6 +1434,9 @@ protected:
bool m_valid;
bool m_suppress_stop_hooks;
bool m_is_dummy_target;
+ bool m_is_scriptable;
+ llvm::Optional<lldb_private::ScriptedProcessLaunchInfo>
+ m_scripted_process_launch_info;
unsigned m_next_persistent_variable_index = 0;
/// An optional \a lldb_private::Trace object containing processor trace
/// information of this target.
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index a297a928a3f4..01eea3d46035 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -340,6 +340,7 @@ typedef std::shared_ptr<lldb_private::LineTable> LineTableSP;
typedef std::shared_ptr<lldb_private::Listener> ListenerSP;
typedef std::weak_ptr<lldb_private::Listener> ListenerWP;
typedef std::shared_ptr<lldb_private::MemoryHistory> MemoryHistorySP;
+typedef std::shared_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoSP;
typedef std::unique_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoUP;
typedef std::shared_ptr<lldb_private::Module> ModuleSP;
typedef std::weak_ptr<lldb_private::Module> ModuleWP;
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.">;
diff --git a/lldb/source/Plugins/Process/Scripted/CMakeLists.txt b/lldb/source/Plugins/Process/Scripted/CMakeLists.txt
new file mode 100644
index 000000000000..0a3b3bc538a3
--- /dev/null
+++ b/lldb/source/Plugins/Process/Scripted/CMakeLists.txt
@@ -0,0 +1,21 @@
+lldb_tablegen(ScriptedProcessOptions.inc -gen-lldb-option-defs
+ SOURCE ScriptedProcessOptions.td
+ TARGET LLDBPluginScriptedProcessOptionGen)
+
+add_lldb_library(lldbPluginScriptedProcess PLUGIN
+ ScriptedProcess.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbTarget
+ lldbUtility
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ BinaryFormat
+ Object
+ Support
+ )
+
+add_dependencies(lldbPluginScriptedProcess
+ LLDBPluginScriptedProcessOptionGen
+)
diff --git a/lldb/source/Plugins/Process/Scripted/ScriptedProcessOptions.td b/lldb/source/Plugins/Process/Scripted/ScriptedProcessOptions.td
new file mode 100644
index 000000000000..55ea06e6de65
--- /dev/null
+++ b/lldb/source/Plugins/Process/Scripted/ScriptedProcessOptions.td
@@ -0,0 +1,7 @@
+include "../../../Commands/OptionsBase.td"
+
+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.">;
+}
diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
index 6f03825cd6cd..ae57051a60b0 100644
--- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
+++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
@@ -27,8 +27,8 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
-#include "ProcessMachCore.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
+#include "ProcessMachCore.h"
#include "ThreadMachCore.h"
// Needed for the plug-in names for the dynamic loaders.
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 6b53bd3a2edc..cc645edd4220 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -2148,6 +2148,198 @@ ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) {
return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
}
+#pragma mark ScriptedProcessInterface
+
+// StructuredData::GenericSP
+// ScriptInterpreterPythonImpl::ScriptedProcess_CreatePluginObject(
+// const char
+// *class_name,
+// lldb::ProcessSP
+// process_sp) {
+// if (class_name == nullptr || class_name[0] == '\0')
+// return StructuredData::GenericSP();
+//
+// if (!process_sp)
+// return StructuredData::GenericSP();
+//
+// void *ret_val;
+//
+// {
+// Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,
+// Locker::FreeLock);
+// ret_val = LLDBSWIGPythonCreateOSPlugin(
+// class_name,
+// m_dictionary_name.c_str(),
+// process_sp);
+// }
+//
+// return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+//}
+
+StructuredData::DictionarySP
+ScriptInterpreterPythonImpl::ScriptedProcess_Create(
+ StructuredData::ObjectSP scripted_process_object_sp, lldb::pid_t pid,
+ lldb::addr_t context) {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ static char callee_name[] = "create_process";
+ std::string param_format;
+ param_format += GetPythonValueFormatString(pid);
+ param_format += GetPythonValueFormatString(context);
+
+ if (!scripted_process_object_sp)
+ return StructuredData::DictionarySP();
+
+ StructuredData::Generic *generic = scripted_process_object_sp->GetAsGeneric();
+ if (!generic)
+ return nullptr;
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return StructuredData::DictionarySP();
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name,
+ &param_format[0], pid, context));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.get()) {
+ PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
+ return result_dict.CreateStructuredDictionary();
+ }
+ return StructuredData::DictionarySP();
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPythonImpl::ScriptedProcess_GetNumMemoryRegions(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ static char callee_name[] = "get_num_memory_regions";
+
+ if (!scripted_process_object_sp)
+ return StructuredData::DictionarySP();
+
+ StructuredData::Generic *generic = scripted_process_object_sp->GetAsGeneric();
+ if (!generic)
+ return nullptr;
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return StructuredData::DictionarySP();
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(
+ PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.get()) {
+ PythonDictionary result(PyRefType::Borrowed, py_return.get());
+ return result.CreateStructuredDictionary();
+ }
+ return StructuredData::DictionarySP();
+}
+
+lldb::MemoryRegionInfoSP
+ScriptInterpreterPythonImpl::ScriptedProcess_GetMemoryRegionAtIndex(
+ StructuredData::ObjectSP scripted_process_object_sp, size_t index) {
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPythonImpl::ScriptedProcess_GetNumThreads(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPythonImpl::ScriptedProcess_GetThreadAtIndex(
+ StructuredData::ObjectSP scripted_process_object_sp, size_t index) {
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPythonImpl::ScriptedProcess_GetRegisterForThread(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPythonImpl::ScriptedProcess_ReadMemoryAtAddress(
+ StructuredData::ObjectSP scripted_process_object_sp, lldb::addr_t address,
+ size_t size) {
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPythonImpl::ScriptedProcess_GetLoadedImages(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPythonImpl::ScriptedProcess_CanDebug(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPythonImpl::ScriptedProcess_IsAlive(
+ StructuredData::ObjectSP scripted_process_object_sp) {
+ return nullptr;
+}
+
bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(
const char *oneliner, std::string &output, const void *name_token) {
StringList input;
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 45dad4217005..17a8fc5ca6d3 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -74,6 +74,44 @@ public:
StructuredData::GenericSP
CreateScriptCommandObject(const char *class_name) override;
+ StructuredData::DictionarySP ScriptedProcess_CreatePluginObject(
+ StructuredData::ObjectSP scripted_process_object_sp, lldb::pid_t pid,
+ lldb::addr_t context);
+
+ StructuredData::DictionarySP
+ ScriptedProcess_Create(StructuredData::ObjectSP scripted_process_object_sp,
+ lldb::pid_t pid, lldb::addr_t context) override;
+
+ StructuredData::DictionarySP ScriptedProcess_GetNumMemoryRegions(
+ StructuredData::ObjectSP scripted_process_object_sp) override;
+
+ lldb::MemoryRegionInfoSP ScriptedProcess_GetMemoryRegionAtIndex(
+ StructuredData::ObjectSP scripted_process_object_sp,
+ size_t index) override;
+
+ StructuredData::DictionarySP ScriptedProcess_GetNumThreads(
+ StructuredData::ObjectSP scripted_process_object_sp) override;
+
+ StructuredData::DictionarySP ScriptedProcess_GetThreadAtIndex(
+ StructuredData::ObjectSP scripted_process_object_sp,
+ size_t index) override;
+
+ StructuredData::DictionarySP ScriptedProcess_GetRegisterForThread(
+ StructuredData::ObjectSP scripted_process_object_sp) override;
+
+ StructuredData::DictionarySP ScriptedProcess_ReadMemoryAtAddress(
+ StructuredData::ObjectSP scripted_process_object_sp, lldb::addr_t address,
+ size_t size) override;
+
+ StructuredData::DictionarySP ScriptedProcess_GetLoadedImages(
+ StructuredData::ObjectSP scripted_process_object_sp) override;
+
+ StructuredData::DictionarySP ScriptedProcess_CanDebug(
+ StructuredData::ObjectSP scripted_process_object_sp) override;
+
+ StructuredData::DictionarySP ScriptedProcess_IsAlive(
+ StructuredData::ObjectSP scripted_process_object_sp) override;
+
StructuredData::ObjectSP
CreateScriptedThreadPlan(const char *class_name,
StructuredDataImpl *args_data,
diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt
index 383ac5a6c53c..cf3275436be0 100644
--- a/lldb/source/Target/CMakeLists.txt
+++ b/lldb/source/Target/CMakeLists.txt
@@ -32,6 +32,7 @@ add_lldb_library(lldbTarget
RegisterContextUnwind.cpp
RegisterNumber.cpp
RemoteAwarePlatform.cpp
+ ScriptedProcess.cpp
SectionLoadHistory.cpp
SectionLoadList.cpp
StackFrame.cpp
@@ -55,6 +56,7 @@ add_lldb_library(lldbTarget
ThreadPlanPython.cpp
ThreadPlanRunToAddress.cpp
ThreadPlanShouldStopHere.cpp
+ ThreadPlanStack.cpp
ThreadPlanStepInRange.cpp
ThreadPlanStepInstruction.cpp
ThreadPlanStepOut.cpp
@@ -64,7 +66,6 @@ add_lldb_library(lldbTarget
ThreadPlanStepThrough.cpp
ThreadPlanStepUntil.cpp
ThreadPlanTracer.cpp
- ThreadPlanStack.cpp
ThreadSpec.cpp
ThreadTrace.cpp
Trace.cpp
diff --git a/lldb/source/Target/ScriptedProcess.cpp b/lldb/source/Target/ScriptedProcess.cpp
new file mode 100644
index 000000000000..d02acee3eea5
--- /dev/null
+++ b/lldb/source/Target/ScriptedProcess.cpp
@@ -0,0 +1,286 @@
+//===-- ScriptedProcess.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 "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+
+//#include "lldb/Core/ModuleSpec.h"
+
+#include "lldb/Core/PluginManager.h"
+
+//#include "lldb/Core/Section.h"
+
+#include "lldb/Host/OptionParser.h"
+
+#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionGroupBoolean.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/ScriptedProcess.h"
+//#include "lldb/Target/SectionLoadList.h"
+//#include "lldb/Target/Target.h"
+//#include "lldb/Target/UnixSignals.h"
+//#include "lldb/Utility/LLDBAssert.h"
+//#include "lldb/Utility/Log.h"
+//#include "lldb/Utility/State.h"
+//#include "llvm/BinaryFormat/Magic.h"
+//#include "llvm/Support/MemoryBuffer.h"
+//#include "llvm/Support/Threading.h"
+
+//#include <memory>
+
+using namespace lldb;
+using namespace lldb_private;
+
+lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *file,
+ bool can_connect) {
+
+ // TODO: Check FileSpec content ?
+ if (!target_sp->IsScriptable()) {
+ return nullptr;
+ }
+
+ const ScriptedProcessLaunchInfo &launch_info =
+ *target_sp->GetScriptedProcessLaunchInfo();
+
+ return std::make_shared<ScriptedProcess>(target_sp, listener_sp, launch_info);
+}
+
+bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) {
+ return true;
+}
+
+ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const ScriptedProcessLaunchInfo &launch_info)
+ : Process(target_sp, listener_sp), m_launch_info(launch_info),
+ m_interpreter_sp(nullptr), m_python_object_sp(nullptr) {
+ if (!target_sp)
+ return;
+
+ m_interpreter_sp.reset(target_sp->GetDebugger().GetScriptInterpreter());
+
+ if (!m_interpreter_sp)
+ return;
+
+ const FileSpec &script_file = m_launch_info.GetScriptFileSpec();
+
+ std::string scripted_process_plugin_class_name(
+ script_file.GetFilename().AsCString(""));
+ if (!scripted_process_plugin_class_name.empty()) {
+ const std::string scripted_process_plugin_path = script_file.GetPath();
+ const bool init_session = false;
+ Status error;
+ if (m_interpreter_sp->LoadScriptingModule(
+ scripted_process_plugin_path.c_str(), init_session, error)) {
+ // Strip the ".py" extension if there is one
+ size_t py_extension_pos = scripted_process_plugin_class_name.rfind(".py");
+ if (py_extension_pos != std::string::npos)
+ scripted_process_plugin_class_name.erase(py_extension_pos);
+ // Add ".OperatingSystemPlugIn" to the module name to get a string like
+ // "modulename.OperatingSystemPlugIn"
+ scripted_process_plugin_class_name += ".OperatingSystemPlugIn";
+
+ StructuredData::ObjectSP object_sp =
+ m_interpreter_sp->ScriptedProcess_Create(NULL, 0,
+ LLDB_INVALID_ADDRESS);
+ // m_interpreter_sp->OSPlugin_CreatePluginObject(scripted_process_plugin_class_name.c_str(),
+ // process->CalculateProcess());
+ if (object_sp && object_sp->IsValid())
+ m_python_object_sp = object_sp;
+ }
+ }
+}
+
+ScriptedProcess::~ScriptedProcess() {
+ Clear();
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
+ Finalize();
+}
+
+void ScriptedProcess::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+ });
+}
+
+void ScriptedProcess::Terminate() {
+ PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
+}
+
+ConstString ScriptedProcess::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t ScriptedProcess::GetPluginVersion() { return 1; }
+
+Status ScriptedProcess::DoDestroy() { return Status(); }
+
+void ScriptedProcess::RefreshStateAfterStop() {
+ //
+ // if (!m_active_exception)
+ // return;
+ //
+ // constexpr uint32_t BreakpadDumpRequested = 0xFFFFFFFF;
+ // if (m_active_exception->ExceptionRecord.ExceptionCode ==
+ // BreakpadDumpRequested) {
+ // // This "ExceptionCode" value is a sentinel that is sometimes used
+ // // when generating a dump for a process that hasn't crashed.
+ //
+ // // TODO: The definition and use of this "dump requested" constant
+ // // in Breakpad are actually Linux-specific, and for similar use
+ // // cases on Mac/Windows it defines different constants, referring
+ // // to them as "simulated" exceptions; consider moving this check
+ // // down to the OS-specific paths and checking each OS for its own
+ // // constant.
+ // return;
+ // }
+ //
+ // lldb::StopInfoSP stop_info;
+ // lldb::ThreadSP stop_thread;
+ //
+ // Process::m_thread_list.SetSelectedThreadByID(m_active_exception->ThreadId);
+ // stop_thread = Process::m_thread_list.GetSelectedThread();
+ // ArchSpec arch = GetArchitecture();
+ //
+ // if (arch.GetTriple().getOS() == llvm::Triple::Linux) {
+ // uint32_t signo = m_active_exception->ExceptionRecord.ExceptionCode;
+ //
+ // if (signo == 0) {
+ // // No stop.
+ // return;
+ // }
+ //
+ // stop_info = StopInfo::CreateStopReasonWithSignal(
+ // *stop_thread, signo);
+ // } else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) {
+ // stop_info = StopInfoMachException::CreateStopReasonWithMachException(
+ // *stop_thread,
+ // m_active_exception->ExceptionRecord.ExceptionCode,
+ // 2,
+ // m_active_exception->ExceptionRecord.ExceptionFlags,
+ // m_active_exception->ExceptionRecord.ExceptionAddress,
+ // 0);
+ // } else {
+ // std::string desc;
+ // llvm::raw_string_ostream desc_stream(desc);
+ // desc_stream << "Exception "
+ // << llvm::format_hex(
+ // m_active_exception->ExceptionRecord.ExceptionCode,
+ // 8)
+ // << " encountered at address "
+ // << llvm::format_hex(
+ // m_active_exception->ExceptionRecord.ExceptionAddress,
+ // 8);
+ // stop_info = StopInfo::CreateStopReasonWithException(
+ // *stop_thread,
+ // desc_stream.str().c_str());
+ // }
+ //
+ // stop_thread->SetStopInfo(stop_info);
+}
+
+bool ScriptedProcess::IsAlive() { return true; }
+
+bool ScriptedProcess::WarnBeforeDetach() const { return false; }
+
+size_t ScriptedProcess::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) {
+ // Don't allow the caching that lldb_private::Process::ReadMemory does since
+ // we have it all cached in our dump file anyway.
+
+ return DoReadMemory(addr, buf, size, error);
+}
+
+size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) {
+
+ m_interpreter_sp->ScriptedProcess_ReadMemoryAtAddress(m_python_object_sp,
+ addr, size);
+ return size;
+}
+
+ArchSpec ScriptedProcess::GetArchitecture() {
+ llvm::Triple triple;
+ // triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
+ // triple.setArch(llvm::Triple::ArchType::x86);
+ // triple.setOS(llvm::Triple::OSType::Win32);
+ return ArchSpec(triple);
+}
+
+Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &region) {
+ // BuildMemoryRegions();
+ // region = MinidumpParser::GetMemoryRegionInfo(*m_memory_regions,
+ // load_addr);
+ return Status();
+}
+
+Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
+ Status error;
+ auto res =
+ m_interpreter_sp->ScriptedProcess_GetNumMemoryRegions(m_python_object_sp);
+
+ if (!res) {
+ error.SetErrorString(
+ "ScriptedProcess: Couldn't get number of memory regions!");
+ return error;
+ }
+
+ uint64_t size = res->GetAsInteger()->GetValue();
+
+ if (size == UINT64_MAX) {
+ error.SetErrorString("ScriptedProcess: Invalid number of memory region!");
+ return error;
+ }
+
+ for (uint64_t i = 0; i < size; i++) {
+ // FIXME: Update interface method to handle extra arg (index)
+ MemoryRegionInfoSP mem_region_sp =
+ m_interpreter_sp->ScriptedProcess_GetMemoryRegionAtIndex(
+ m_python_object_sp, i);
+
+ if (!mem_region_sp) {
+ // FIXME: Interpolate index in error string
+ error.SetErrorString(
+ "ScriptedProcess: Couldn't fetch memory region at index BLA");
+ return error;
+ }
+ region_list.push_back(*mem_region_sp.get());
+ }
+
+ return error;
+}
+
+void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
+
+bool ScriptedProcess::UpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ return new_thread_list.GetSize(false) > 0;
+}
+
+bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
+ info.Clear();
+ info.SetProcessID(GetID());
+ info.SetArchitecture(GetArchitecture());
+ lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
+ if (module_sp) {
+ const bool add_exe_file_as_first_arg = false;
+ info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
+ add_exe_file_as_first_arg);
+ }
+ return true;
+}
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 736864e021bb..46aee0409083 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -96,7 +96,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
m_image_search_paths(ImageSearchPathsChanged, this),
m_source_manager_up(), m_stop_hooks(), m_stop_hook_next_id(0),
m_valid(true), m_suppress_stop_hooks(false),
- m_is_dummy_target(is_dummy_target),
+ m_is_dummy_target(is_dummy_target), m_is_scriptable(false),
m_frame_recognizer_manager_up(
std::make_unique<StackFrameRecognizerManager>()),
m_stats_storage(static_cast<int>(StatisticKind::StatisticMax))