FILES
"${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_process.py")
- create_python_package(
- ${swig_target}
- ${lldb_python_target_dir}
- "plugins"
- FILES
- "${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_process.py")
-
if(APPLE)
create_python_package(
${swig_target}
virtual size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
Status &error) = 0;
+ void SetState(lldb::EventSP &event_sp);
+
lldb::StateType GetPrivateState();
/// The "private" side of resuming a process. This doesn't alter the state
elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(MacOSX-Kernel)
endif()
-add_subdirectory(scripted)
add_subdirectory(gdb-remote)
add_subdirectory(Utility)
add_subdirectory(elf-core)
+++ /dev/null
-add_lldb_library(lldbPluginScriptedProcess PLUGIN
- ScriptedProcess.cpp
-
- LINK_LIBS
- lldbCore
- lldbTarget
- lldbUtility
- lldbPluginProcessUtility
- LINK_COMPONENTS
- BinaryFormat
- Object
- Support
- )
+++ /dev/null
-//===-- 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 "ScriptedProcess.h"
-
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/PluginManager.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"
-
-LLDB_PLUGIN_DEFINE(ScriptedProcess)
-
-using namespace lldb;
-using namespace lldb_private;
-
-ConstString ScriptedProcess::GetPluginNameStatic() {
- static ConstString g_name("ScriptedProcess");
- return g_name;
-}
-
-const char *ScriptedProcess::GetPluginDescriptionStatic() {
- return "Scripted Process plug-in.";
-}
-
-lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
- lldb::ListenerSP listener_sp,
- const FileSpec *file,
- bool can_connect) {
- ScriptedProcess::LaunchInfo launch_info(target_sp->GetProcessLaunchInfo());
-
- auto process_sp =
- std::make_shared<ScriptedProcess>(target_sp, listener_sp, launch_info);
-
- if (!process_sp || !process_sp->m_script_object_sp ||
- !process_sp->m_script_object_sp->IsValid())
- return nullptr;
-
- return process_sp;
-}
-
-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 ScriptedProcess::LaunchInfo &launch_info)
- : Process(target_sp, listener_sp), m_launch_info(launch_info),
- m_interpreter(nullptr), m_script_object_sp(nullptr) {
- if (!target_sp)
- return;
-
- m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
-
- if (!m_interpreter)
- return;
-
- StructuredData::ObjectSP object_sp = GetInterface().CreatePluginObject(
- m_launch_info.GetClassName().c_str(), target_sp,
- m_launch_info.GetDictionarySP());
-
- if (object_sp && object_sp->IsValid())
- m_script_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::DoLoadCore() {
- ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
-
- return DoLaunch(nullptr, launch_info);
-}
-
-Status ScriptedProcess::DoLaunch(Module *exe_module,
- ProcessLaunchInfo &launch_info) {
- if (!m_interpreter)
- return Status("No interpreter.");
-
- if (!m_script_object_sp)
- return Status("No python object.");
-
- Status status = GetInterface().Launch();
-
- if (status.Success()) {
- SetPrivateState(eStateRunning);
- SetPrivateState(eStateStopped);
- }
-
- return status;
-}
-
-void ScriptedProcess::DidLaunch() {
- if (m_interpreter)
- m_pid = GetInterface().GetProcessID();
-}
-
-Status ScriptedProcess::DoResume() {
- if (!m_interpreter)
- return Status("No interpreter.");
-
- if (!m_script_object_sp)
- return Status("No python object.");
-
- Status status = GetInterface().Resume();
-
- if (status.Success()) {
- SetPrivateState(eStateRunning);
- SetPrivateState(eStateStopped);
- }
-
- return status;
-}
-
-Status ScriptedProcess::DoDestroy() { return Status(); }
-
-bool ScriptedProcess::IsAlive() {
- if (!m_interpreter)
- return false;
-
- return GetInterface().IsAlive();
-}
-
-size_t ScriptedProcess::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
- Status &error) {
- return DoReadMemory(addr, buf, size, error);
-}
-
-size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
- Status &error) {
-
- auto error_with_message = [&error](llvm::StringRef message) {
- error.SetErrorString(message);
- return LLDB_INVALID_ADDRESS;
- };
-
- if (!m_interpreter)
- return error_with_message("No interpreter.");
-
- lldb::DataExtractorSP data_extractor_sp =
- GetInterface().ReadMemoryAtAddress(addr, size, error);
-
- if (!data_extractor_sp || error.Fail())
- return LLDB_INVALID_ADDRESS;
-
- if (data_extractor_sp->GetByteSize() != size)
- return error_with_message("Failed to read requested memory size.");
-
- offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
- 0, size, buf, size, GetByteOrder());
-
- if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
- return error_with_message("Failed to copy read memory to buffer.");
-
- return size;
-}
-
-ArchSpec ScriptedProcess::GetArchitecture() {
- return GetTarget().GetArchitecture();
-}
-
-Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
- MemoryRegionInfo ®ion) {
- return Status();
-}
-
-Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) {
- Status error;
-
- if (!m_interpreter) {
- error.SetErrorString("No interpreter.");
- return error;
- }
-
- lldb::addr_t address = 0;
- lldb::MemoryRegionInfoSP mem_region_sp = nullptr;
-
- while ((mem_region_sp =
- GetInterface().GetMemoryRegionContainingAddress(address))) {
- auto range = mem_region_sp->GetRange();
- address += range.GetRangeBase() + range.GetByteSize();
- region_list.push_back(*mem_region_sp.get());
- }
-
- return error;
-}
-
-void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
-
-bool ScriptedProcess::DoUpdateThreadList(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;
-}
-
-ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
- return m_interpreter->GetScriptedProcessInterface();
-}
+++ /dev/null
-//===-- ScriptedProcess.h ------------------------------------- -*- C++ -*-===//
-//
-// 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_SCRIPTED_PROCESS_H
-#define LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H
-
-#include "lldb/Target/Process.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/Status.h"
-
-namespace lldb_private {
-
-class ScriptedProcess : public Process {
-protected:
- class LaunchInfo {
- public:
- LaunchInfo(const ProcessLaunchInfo &launch_info) {
- m_class_name = launch_info.GetScriptedProcessClassName();
- m_dictionary_sp = launch_info.GetScriptedProcessDictionarySP();
- }
-
- std::string GetClassName() const { return m_class_name; }
- StructuredData::DictionarySP GetDictionarySP() const {
- return m_dictionary_sp;
- }
-
- private:
- std::string m_class_name;
- StructuredData::DictionarySP m_dictionary_sp;
- };
-
-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 ScriptedProcess::LaunchInfo &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 DoLoadCore() override;
-
- Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override;
-
- void DidLaunch() override;
-
- Status DoResume() override;
-
- Status DoDestroy() override;
-
- void RefreshStateAfterStop() override{};
-
- bool IsAlive() 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 ®ion_list) override;
-
- bool GetProcessInfo(ProcessInstanceInfo &info) override;
-
-protected:
- void Clear();
-
- bool DoUpdateThreadList(ThreadList &old_thread_list,
- ThreadList &new_thread_list) override;
-
-private:
- ScriptedProcessInterface &GetInterface() const;
-
- const LaunchInfo m_launch_info;
- lldb_private::ScriptInterpreter *m_interpreter;
- lldb_private::StructuredData::ObjectSP m_script_object_sp;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H
// If we're not already connected to the process, and if we have a platform
// that can launch a process for debugging, go ahead and do that here.
if (state != eStateConnected && platform_sp &&
- platform_sp->CanDebugProcess() && !launch_info.IsScriptedProcess()) {
+ platform_sp->CanDebugProcess()) {
LLDB_LOGF(log, "Target::%s asking the platform to debug the process",
__FUNCTION__);
from lldbsuite.test import lldbtest
-class ScriptedProcesTestCase(TestBase):
+class PlatformProcessCrashInfoTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
self.expect('script dir(ScriptedProcess)',
substrs=["launch"])
- def test_launch_scripted_process_sbapi(self):
- """Test that we can launch an lldb scripted process using the SBAPI,
- check its process ID and read string from memory."""
- self.build()
- target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
- self.assertTrue(target, VALID_TARGET)
-
- scripted_process_example_relpath = ['..','..','..','..','examples','python','scripted_process','my_scripted_process.py']
- os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
- self.runCmd("command script import " + os.path.join(self.getSourceDir(),
- *scripted_process_example_relpath))
-
- launch_info = lldb.SBLaunchInfo(None)
- launch_info.SetProcessPluginName("ScriptedProcess")
- launch_info.SetScriptedProcessClassName("my_scripted_process.MyScriptedProcess")
-
- error = lldb.SBError()
- process = target.Launch(launch_info, error)
- self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
- self.assertEqual(process.GetProcessID(), 42)
-
- hello_world = "Hello, world!"
- memory_read = process.ReadCStringFromMemory(0x50000000000,
- len(hello_world) + 1, # NULL byte
- error)
-
- self.assertTrue(error.Success(), "Failed to read memory from scripted process.")
- self.assertEqual(hello_world, memory_read)
-
- def test_launch_scripted_process_cli(self):
- """Test that we can launch an lldb scripted process from the command
- line, check its process ID and read string from memory."""
- self.build()
- target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
- self.assertTrue(target, VALID_TARGET)
-
- scripted_process_example_relpath = ['..','..','..','..','examples','python','scripted_process','my_scripted_process.py']
- self.runCmd("command script import " + os.path.join(self.getSourceDir(),
- *scripted_process_example_relpath))
-
- process = target.GetProcess()
- self.assertTrue(process, PROCESS_IS_VALID)
- self.assertEqual(process.GetProcessID(), 42)
-
- error = lldb.SBError()
- hello_world = "Hello, world!"
- memory_read = process.ReadCStringFromMemory(0x50000000000,
- len(hello_world) + 1, # NULL byte
- error)
-
- self.assertTrue(error.Success(), "Failed to read memory from scripted process.")
- self.assertEqual(hello_world, memory_read)