135653324SMed Ismail Bennani //===-- ScriptedProcessPythonInterface.cpp --------------------------------===//
235653324SMed Ismail Bennani //
335653324SMed Ismail Bennani // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
435653324SMed Ismail Bennani // See https://llvm.org/LICENSE.txt for license information.
535653324SMed Ismail Bennani // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
635653324SMed Ismail Bennani //
735653324SMed Ismail Bennani //===----------------------------------------------------------------------===//
835653324SMed Ismail Bennani 
935653324SMed Ismail Bennani #include "lldb/Core/PluginManager.h"
1035653324SMed Ismail Bennani #include "lldb/Host/Config.h"
1135653324SMed Ismail Bennani #include "lldb/Utility/Log.h"
1235653324SMed Ismail Bennani #include "lldb/Utility/Status.h"
1335653324SMed Ismail Bennani #include "lldb/lldb-enumerations.h"
1435653324SMed Ismail Bennani 
1535653324SMed Ismail Bennani #if LLDB_ENABLE_PYTHON
1635653324SMed Ismail Bennani 
1735653324SMed Ismail Bennani // clang-format off
1835653324SMed Ismail Bennani // LLDB Python header must be included first
1935653324SMed Ismail Bennani #include "../lldb-python.h"
2035653324SMed Ismail Bennani 
2135653324SMed Ismail Bennani #include "../SWIGPythonBridge.h"
2235653324SMed Ismail Bennani #include "../ScriptInterpreterPythonImpl.h"
2335653324SMed Ismail Bennani #include "ScriptedThreadPythonInterface.h"
2435653324SMed Ismail Bennani #include "ScriptedProcessPythonInterface.h"
2535653324SMed Ismail Bennani 
2635653324SMed Ismail Bennani // Included in this position to prevent redefinition of pid_t on Windows.
2735653324SMed Ismail Bennani #include "lldb/Target/Process.h"
2835653324SMed Ismail Bennani //clang-format off
2935653324SMed Ismail Bennani 
3035653324SMed Ismail Bennani #include <optional>
3135653324SMed Ismail Bennani 
3235653324SMed Ismail Bennani using namespace lldb;
3335653324SMed Ismail Bennani using namespace lldb_private;
3435653324SMed Ismail Bennani using namespace lldb_private::python;
3535653324SMed Ismail Bennani using Locker = ScriptInterpreterPythonImpl::Locker;
3635653324SMed Ismail Bennani 
3735653324SMed Ismail Bennani ScriptedProcessPythonInterface::ScriptedProcessPythonInterface(
3835653324SMed Ismail Bennani     ScriptInterpreterPythonImpl &interpreter)
3935653324SMed Ismail Bennani     : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {}
4035653324SMed Ismail Bennani 
4135653324SMed Ismail Bennani llvm::Expected<StructuredData::GenericSP>
4235653324SMed Ismail Bennani ScriptedProcessPythonInterface::CreatePluginObject(
4335653324SMed Ismail Bennani     llvm::StringRef class_name, ExecutionContext &exe_ctx,
4435653324SMed Ismail Bennani     StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
4535653324SMed Ismail Bennani   ExecutionContextRefSP exe_ctx_ref_sp =
4635653324SMed Ismail Bennani       std::make_shared<ExecutionContextRef>(exe_ctx);
4735653324SMed Ismail Bennani   StructuredDataImpl sd_impl(args_sp);
4835653324SMed Ismail Bennani   return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj,
4935653324SMed Ismail Bennani                                                      exe_ctx_ref_sp, sd_impl);
5035653324SMed Ismail Bennani }
5135653324SMed Ismail Bennani 
5235653324SMed Ismail Bennani StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() {
5335653324SMed Ismail Bennani   Status error;
5435653324SMed Ismail Bennani   StructuredData::DictionarySP dict =
5535653324SMed Ismail Bennani       Dispatch<StructuredData::DictionarySP>("get_capabilities", error);
5635653324SMed Ismail Bennani 
5735653324SMed Ismail Bennani   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
5835653324SMed Ismail Bennani                                                     error))
5935653324SMed Ismail Bennani     return {};
6035653324SMed Ismail Bennani 
6135653324SMed Ismail Bennani   return dict;
6235653324SMed Ismail Bennani }
6335653324SMed Ismail Bennani 
6435653324SMed Ismail Bennani Status
6535653324SMed Ismail Bennani ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) {
6635653324SMed Ismail Bennani   lldb::ProcessAttachInfoSP attach_info_sp =
6735653324SMed Ismail Bennani       std::make_shared<ProcessAttachInfo>(attach_info);
6835653324SMed Ismail Bennani   return GetStatusFromMethod("attach", attach_info_sp);
6935653324SMed Ismail Bennani }
7035653324SMed Ismail Bennani 
7135653324SMed Ismail Bennani Status ScriptedProcessPythonInterface::Launch() {
7235653324SMed Ismail Bennani   return GetStatusFromMethod("launch");
7335653324SMed Ismail Bennani }
7435653324SMed Ismail Bennani 
7535653324SMed Ismail Bennani Status ScriptedProcessPythonInterface::Resume() {
7635653324SMed Ismail Bennani   // When calling ScriptedProcess.Resume from lldb we should always stop.
7735653324SMed Ismail Bennani   return GetStatusFromMethod("resume", /*should_stop=*/true);
7835653324SMed Ismail Bennani }
7935653324SMed Ismail Bennani 
8035653324SMed Ismail Bennani std::optional<MemoryRegionInfo>
8135653324SMed Ismail Bennani ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
8235653324SMed Ismail Bennani     lldb::addr_t address, Status &error) {
8335653324SMed Ismail Bennani   auto mem_region = Dispatch<std::optional<MemoryRegionInfo>>(
8435653324SMed Ismail Bennani       "get_memory_region_containing_address", error, address);
8535653324SMed Ismail Bennani 
8635653324SMed Ismail Bennani   if (error.Fail()) {
8735653324SMed Ismail Bennani     return ErrorWithMessage<MemoryRegionInfo>(LLVM_PRETTY_FUNCTION,
8835653324SMed Ismail Bennani                                               error.AsCString(), error);
8935653324SMed Ismail Bennani   }
9035653324SMed Ismail Bennani 
9135653324SMed Ismail Bennani   return mem_region;
9235653324SMed Ismail Bennani }
9335653324SMed Ismail Bennani 
9435653324SMed Ismail Bennani StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() {
9535653324SMed Ismail Bennani   Status error;
9635653324SMed Ismail Bennani   StructuredData::DictionarySP dict =
9735653324SMed Ismail Bennani       Dispatch<StructuredData::DictionarySP>("get_threads_info", error);
9835653324SMed Ismail Bennani 
9935653324SMed Ismail Bennani   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
10035653324SMed Ismail Bennani                                                     error))
10135653324SMed Ismail Bennani     return {};
10235653324SMed Ismail Bennani 
10335653324SMed Ismail Bennani   return dict;
10435653324SMed Ismail Bennani }
10535653324SMed Ismail Bennani 
10635653324SMed Ismail Bennani bool ScriptedProcessPythonInterface::CreateBreakpoint(lldb::addr_t addr,
10735653324SMed Ismail Bennani                                                       Status &error) {
10835653324SMed Ismail Bennani   Status py_error;
10935653324SMed Ismail Bennani   StructuredData::ObjectSP obj =
11035653324SMed Ismail Bennani       Dispatch("create_breakpoint", py_error, addr, error);
11135653324SMed Ismail Bennani 
11235653324SMed Ismail Bennani   // If there was an error on the python call, surface it to the user.
11335653324SMed Ismail Bennani   if (py_error.Fail())
114*b798f4bdSAdrian Prantl     error = std::move(py_error);
11535653324SMed Ismail Bennani 
11635653324SMed Ismail Bennani   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
11735653324SMed Ismail Bennani                                                     error))
11835653324SMed Ismail Bennani     return {};
11935653324SMed Ismail Bennani 
12035653324SMed Ismail Bennani   return obj->GetBooleanValue();
12135653324SMed Ismail Bennani }
12235653324SMed Ismail Bennani 
12335653324SMed Ismail Bennani lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
12435653324SMed Ismail Bennani     lldb::addr_t address, size_t size, Status &error) {
12535653324SMed Ismail Bennani   Status py_error;
12635653324SMed Ismail Bennani   lldb::DataExtractorSP data_sp = Dispatch<lldb::DataExtractorSP>(
12735653324SMed Ismail Bennani       "read_memory_at_address", py_error, address, size, error);
12835653324SMed Ismail Bennani 
12935653324SMed Ismail Bennani   // If there was an error on the python call, surface it to the user.
13035653324SMed Ismail Bennani   if (py_error.Fail())
131*b798f4bdSAdrian Prantl     error = std::move(py_error);
13235653324SMed Ismail Bennani 
13335653324SMed Ismail Bennani   return data_sp;
13435653324SMed Ismail Bennani }
13535653324SMed Ismail Bennani 
13635653324SMed Ismail Bennani lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress(
13735653324SMed Ismail Bennani     lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) {
13835653324SMed Ismail Bennani   Status py_error;
13935653324SMed Ismail Bennani   StructuredData::ObjectSP obj =
14035653324SMed Ismail Bennani       Dispatch("write_memory_at_address", py_error, addr, data_sp, error);
14135653324SMed Ismail Bennani 
14235653324SMed Ismail Bennani   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
14335653324SMed Ismail Bennani                                                     error))
14435653324SMed Ismail Bennani     return LLDB_INVALID_OFFSET;
14535653324SMed Ismail Bennani 
14635653324SMed Ismail Bennani   // If there was an error on the python call, surface it to the user.
14735653324SMed Ismail Bennani   if (py_error.Fail())
148*b798f4bdSAdrian Prantl     error = std::move(py_error);
14935653324SMed Ismail Bennani 
15035653324SMed Ismail Bennani   return obj->GetUnsignedIntegerValue(LLDB_INVALID_OFFSET);
15135653324SMed Ismail Bennani }
15235653324SMed Ismail Bennani 
15335653324SMed Ismail Bennani StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() {
15435653324SMed Ismail Bennani   Status error;
15535653324SMed Ismail Bennani   StructuredData::ArraySP array =
15635653324SMed Ismail Bennani       Dispatch<StructuredData::ArraySP>("get_loaded_images", error);
15735653324SMed Ismail Bennani 
15835653324SMed Ismail Bennani   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, array,
15935653324SMed Ismail Bennani                                                     error))
16035653324SMed Ismail Bennani     return {};
16135653324SMed Ismail Bennani 
16235653324SMed Ismail Bennani   return array;
16335653324SMed Ismail Bennani }
16435653324SMed Ismail Bennani 
16535653324SMed Ismail Bennani lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
16635653324SMed Ismail Bennani   Status error;
16735653324SMed Ismail Bennani   StructuredData::ObjectSP obj = Dispatch("get_process_id", error);
16835653324SMed Ismail Bennani 
16935653324SMed Ismail Bennani   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
17035653324SMed Ismail Bennani                                                     error))
17135653324SMed Ismail Bennani     return LLDB_INVALID_PROCESS_ID;
17235653324SMed Ismail Bennani 
17335653324SMed Ismail Bennani   return obj->GetUnsignedIntegerValue(LLDB_INVALID_PROCESS_ID);
17435653324SMed Ismail Bennani }
17535653324SMed Ismail Bennani 
17635653324SMed Ismail Bennani bool ScriptedProcessPythonInterface::IsAlive() {
17735653324SMed Ismail Bennani   Status error;
17835653324SMed Ismail Bennani   StructuredData::ObjectSP obj = Dispatch("is_alive", error);
17935653324SMed Ismail Bennani 
18035653324SMed Ismail Bennani   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
18135653324SMed Ismail Bennani                                                     error))
18235653324SMed Ismail Bennani     return {};
18335653324SMed Ismail Bennani 
18435653324SMed Ismail Bennani   return obj->GetBooleanValue();
18535653324SMed Ismail Bennani }
18635653324SMed Ismail Bennani 
18735653324SMed Ismail Bennani std::optional<std::string>
18835653324SMed Ismail Bennani ScriptedProcessPythonInterface::GetScriptedThreadPluginName() {
18935653324SMed Ismail Bennani   Status error;
19035653324SMed Ismail Bennani   StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error);
19135653324SMed Ismail Bennani 
19235653324SMed Ismail Bennani   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
19335653324SMed Ismail Bennani                                                     error))
19435653324SMed Ismail Bennani     return {};
19535653324SMed Ismail Bennani 
19635653324SMed Ismail Bennani   return obj->GetStringValue().str();
19735653324SMed Ismail Bennani }
19835653324SMed Ismail Bennani 
19935653324SMed Ismail Bennani lldb::ScriptedThreadInterfaceSP
20035653324SMed Ismail Bennani ScriptedProcessPythonInterface::CreateScriptedThreadInterface() {
20135653324SMed Ismail Bennani   return m_interpreter.CreateScriptedThreadInterface();
20235653324SMed Ismail Bennani }
20335653324SMed Ismail Bennani 
20435653324SMed Ismail Bennani StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() {
20535653324SMed Ismail Bennani   Status error;
20635653324SMed Ismail Bennani   StructuredData::DictionarySP dict =
20735653324SMed Ismail Bennani       Dispatch<StructuredData::DictionarySP>("get_process_metadata", error);
20835653324SMed Ismail Bennani 
20935653324SMed Ismail Bennani   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
21035653324SMed Ismail Bennani                                                     error))
21135653324SMed Ismail Bennani     return {};
21235653324SMed Ismail Bennani 
21335653324SMed Ismail Bennani   return dict;
21435653324SMed Ismail Bennani }
21535653324SMed Ismail Bennani 
21635653324SMed Ismail Bennani void ScriptedProcessPythonInterface::Initialize() {
21735653324SMed Ismail Bennani   const std::vector<llvm::StringRef> ci_usages = {
21835653324SMed Ismail Bennani       "process attach -C <script-name> [-k key -v value ...]",
21935653324SMed Ismail Bennani       "process launch -C <script-name> [-k key -v value ...]"};
22035653324SMed Ismail Bennani   const std::vector<llvm::StringRef> api_usages = {
22135653324SMed Ismail Bennani       "SBAttachInfo.SetScriptedProcessClassName",
22235653324SMed Ismail Bennani       "SBAttachInfo.SetScriptedProcessDictionary",
22335653324SMed Ismail Bennani       "SBTarget.Attach",
22435653324SMed Ismail Bennani       "SBLaunchInfo.SetScriptedProcessClassName",
22535653324SMed Ismail Bennani       "SBLaunchInfo.SetScriptedProcessDictionary",
22635653324SMed Ismail Bennani       "SBTarget.Launch"};
22735653324SMed Ismail Bennani   PluginManager::RegisterPlugin(
22835653324SMed Ismail Bennani       GetPluginNameStatic(), llvm::StringRef("Mock process state"),
22935653324SMed Ismail Bennani       CreateInstance, eScriptLanguagePython, {ci_usages, api_usages});
23035653324SMed Ismail Bennani }
23135653324SMed Ismail Bennani 
23235653324SMed Ismail Bennani void ScriptedProcessPythonInterface::Terminate() {
23335653324SMed Ismail Bennani   PluginManager::UnregisterPlugin(CreateInstance);
23435653324SMed Ismail Bennani }
23535653324SMed Ismail Bennani 
23635653324SMed Ismail Bennani #endif
237