[llvm-branch-commits] [lldb] 68e6321 - [lldb/Target] Add Scripted Processes (WIP)

Med Ismail Bennani via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Jan 9 08:34:31 PST 2021


Author: Med Ismail Bennani
Date: 2021-01-08T21:23:34+01:00
New Revision: 68e63210aeb74d2ef6ef0110da80d1aa78ba4148

URL: https://github.com/llvm/llvm-project/commit/68e63210aeb74d2ef6ef0110da80d1aa78ba4148
DIFF: https://github.com/llvm/llvm-project/commit/68e63210aeb74d2ef6ef0110da80d1aa78ba4148.diff

LOG: [lldb/Target] Add Scripted Processes (WIP)

Signed-off-by: Med Ismail Bennani <medismail.bennani at gmail.com>

Added: 
    lldb/bindings/python/python-scripted-process.swig
    lldb/examples/python/scripted_process.py
    lldb/include/lldb/Target/ScriptedProcess.h
    lldb/source/Commands/CommandObjectProcessScripted.cpp
    lldb/source/Commands/CommandObjectProcessScripted.h
    lldb/source/Plugins/Process/Scripted/CMakeLists.txt
    lldb/source/Plugins/Process/Scripted/ScriptedProcessOptions.td
    lldb/source/Target/ScriptedProcess.cpp

Modified: 
    lldb/bindings/python/python.swig
    lldb/include/lldb/Host/ProcessLaunchInfo.h
    lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h
    lldb/include/lldb/Interpreter/ScriptInterpreter.h
    lldb/include/lldb/Target/Target.h
    lldb/include/lldb/lldb-forward.h
    lldb/source/Commands/CMakeLists.txt
    lldb/source/Commands/CommandObjectProcess.cpp
    lldb/source/Commands/Options.td
    lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
    lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
    lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
    lldb/source/Target/CMakeLists.txt
    lldb/source/Target/Target.cpp

Removed: 
    


################################################################################
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 @@ class ProcessLaunchInfo : public ProcessInfo {
   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 @@ class OptionGroupPythonClassWithDict : public OptionGroup {
     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 @@ class ScriptInterpreter : public PluginInterface {
 
   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 @@ class Target : public std::enable_shared_from_this<Target>,
 
   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 @@ class Target : public std::enable_shared_from_this<Target>,
   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 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
   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 
diff erent 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))


        


More information about the llvm-branch-commits mailing list