[Lldb-commits] [lldb] [lldb] Expose SBPlatform::GetAllProcesses to the SB API (PR #68378)

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Thu Oct 5 21:08:34 PDT 2023


https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/68378

Add the ability to list all processes through the SB API.

rdar://116188959

>From 8611bebd2b6cd4f6de797240c1cb184af71f384d Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 5 Oct 2023 21:07:03 -0700
Subject: [PATCH] [lldb] Expose SBPlatform::GetAllProcesses to the SB API

Add the ability to list all processes through the SB API.

rdar://116188959
---
 lldb/bindings/headers.swig                    |  1 +
 .../interface/SBProcessInfoListExtensions.i   | 13 ++++
 lldb/bindings/interfaces.swig                 |  2 +
 lldb/include/lldb/API/LLDB.h                  |  1 +
 lldb/include/lldb/API/SBDefines.h             |  1 +
 lldb/include/lldb/API/SBPlatform.h            |  4 +
 lldb/include/lldb/API/SBProcessInfo.h         |  1 +
 lldb/include/lldb/API/SBProcessInfoList.h     | 46 ++++++++++++
 lldb/include/lldb/Target/Platform.h           |  4 +-
 lldb/include/lldb/Utility/ProcessInfo.h       | 20 +++++
 lldb/source/API/CMakeLists.txt                |  1 +
 lldb/source/API/SBPlatform.cpp                | 15 ++++
 lldb/source/API/SBProcessInfoList.cpp         | 73 +++++++++++++++++++
 lldb/source/Target/Platform.cpp               |  8 ++
 .../TestPlatformListProcesses.py              | 54 ++++++++++++++
 15 files changed, 243 insertions(+), 1 deletion(-)
 create mode 100644 lldb/bindings/interface/SBProcessInfoListExtensions.i
 create mode 100644 lldb/include/lldb/API/SBProcessInfoList.h
 create mode 100644 lldb/source/API/SBProcessInfoList.cpp
 create mode 100644 lldb/test/API/functionalities/gdb_remote_client/TestPlatformListProcesses.py

diff --git a/lldb/bindings/headers.swig b/lldb/bindings/headers.swig
index d392ed43d8c0c9e..b1d88726f754354 100644
--- a/lldb/bindings/headers.swig
+++ b/lldb/bindings/headers.swig
@@ -46,6 +46,7 @@
 #include "lldb/API/SBPlatform.h"
 #include "lldb/API/SBProcess.h"
 #include "lldb/API/SBProcessInfo.h"
+#include "lldb/API/SBProcessInfoList.h"
 #include "lldb/API/SBQueue.h"
 #include "lldb/API/SBQueueItem.h"
 #include "lldb/API/SBReproducer.h"
diff --git a/lldb/bindings/interface/SBProcessInfoListExtensions.i b/lldb/bindings/interface/SBProcessInfoListExtensions.i
new file mode 100644
index 000000000000000..42999846ef6a52f
--- /dev/null
+++ b/lldb/bindings/interface/SBProcessInfoListExtensions.i
@@ -0,0 +1,13 @@
+%extend lldb::SBProcessInfoList {
+#ifdef SWIGPYTHON
+    %pythoncode%{
+    def __len__(self):
+      '''Return the number of process info in a lldb.SBProcessInfoListExtensions object.'''
+      return self.GetSize()
+
+    def __iter__(self):
+      '''Iterate over all the process info in a lldb.SBProcessInfoListExtensions object.'''
+      return lldb_iter(self, 'GetSize', 'GetProcessInfoAtIndex')
+    %}
+#endif
+}
diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index 306cfe683893271..373c2f6cf545cfb 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -122,6 +122,7 @@
 %include "lldb/API/SBPlatform.h"
 %include "lldb/API/SBProcess.h"
 %include "lldb/API/SBProcessInfo.h"
+%include "lldb/API/SBProcessInfoList.h"
 %include "lldb/API/SBQueue.h"
 %include "lldb/API/SBQueueItem.h"
 %include "lldb/API/SBReproducer.h"
@@ -184,6 +185,7 @@
 %include "./interface/SBModuleSpecExtensions.i"
 %include "./interface/SBModuleSpecListExtensions.i"
 %include "./interface/SBProcessExtensions.i"
+%include "./interface/SBProcessInfoListExtensions.i"
 %include "./interface/SBQueueItemExtensions.i"
 %include "./interface/SBScriptObjectExtensions.i"
 %include "./interface/SBSectionExtensions.i"
diff --git a/lldb/include/lldb/API/LLDB.h b/lldb/include/lldb/API/LLDB.h
index eacbbeafcf1cd86..f652d1bdb835b59 100644
--- a/lldb/include/lldb/API/LLDB.h
+++ b/lldb/include/lldb/API/LLDB.h
@@ -49,6 +49,7 @@
 #include "lldb/API/SBPlatform.h"
 #include "lldb/API/SBProcess.h"
 #include "lldb/API/SBProcessInfo.h"
+#include "lldb/API/SBProcessInfoList.h"
 #include "lldb/API/SBQueue.h"
 #include "lldb/API/SBQueueItem.h"
 #include "lldb/API/SBReproducer.h"
diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h
index ec5e940fdaf36fc..c6f01cc03f263c8 100644
--- a/lldb/include/lldb/API/SBDefines.h
+++ b/lldb/include/lldb/API/SBDefines.h
@@ -90,6 +90,7 @@ class LLDB_API SBPlatformConnectOptions;
 class LLDB_API SBPlatformShellCommand;
 class LLDB_API SBProcess;
 class LLDB_API SBProcessInfo;
+class LLDB_API SBProcessInfoList;
 class LLDB_API SBQueue;
 class LLDB_API SBQueueItem;
 class LLDB_API SBReplayOptions;
diff --git a/lldb/include/lldb/API/SBPlatform.h b/lldb/include/lldb/API/SBPlatform.h
index e0acc7003a54bc3..d63d2ed1eaba627 100644
--- a/lldb/include/lldb/API/SBPlatform.h
+++ b/lldb/include/lldb/API/SBPlatform.h
@@ -11,11 +11,13 @@
 
 #include "lldb/API/SBDefines.h"
 #include "lldb/API/SBProcess.h"
+#include "lldb/API/SBProcessInfoList.h"
 
 #include <functional>
 
 struct PlatformConnectOptions;
 struct PlatformShellCommand;
+class ProcessInstanceInfoMatch;
 
 namespace lldb {
 
@@ -154,6 +156,8 @@ class LLDB_API SBPlatform {
   SBProcess Attach(SBAttachInfo &attach_info, const SBDebugger &debugger,
                    SBTarget &target, SBError &error);
 
+  SBProcessInfoList GetAllProcesses(SBError &error);
+
   SBError Kill(const lldb::pid_t pid);
 
   SBError
diff --git a/lldb/include/lldb/API/SBProcessInfo.h b/lldb/include/lldb/API/SBProcessInfo.h
index 36fae9e842a6136..aec5924e4704a49 100644
--- a/lldb/include/lldb/API/SBProcessInfo.h
+++ b/lldb/include/lldb/API/SBProcessInfo.h
@@ -55,6 +55,7 @@ class LLDB_API SBProcessInfo {
 
 private:
   friend class SBProcess;
+  friend class SBProcessInfoList;
 
   lldb_private::ProcessInstanceInfo &ref();
 
diff --git a/lldb/include/lldb/API/SBProcessInfoList.h b/lldb/include/lldb/API/SBProcessInfoList.h
new file mode 100644
index 000000000000000..7591fb3db713874
--- /dev/null
+++ b/lldb/include/lldb/API/SBProcessInfoList.h
@@ -0,0 +1,46 @@
+//===-- SBProcessInfoList.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_API_SBPROCESSINSTANCEINFOLIST_H
+#define LLDB_API_SBPROCESSINSTANCEINFOLIST_H
+
+#include "lldb/API/SBDefines.h"
+
+#include <memory>
+
+namespace lldb_private {
+class ProcessInfoList;
+} // namespace lldb_private
+
+namespace lldb {
+
+class LLDB_API SBProcessInfoList {
+public:
+  SBProcessInfoList();
+  ~SBProcessInfoList();
+
+  SBProcessInfoList(const lldb::SBProcessInfoList &rhs);
+
+  const lldb::SBProcessInfoList &operator=(const lldb::SBProcessInfoList &rhs);
+
+  uint32_t GetSize() const;
+
+  bool GetProcessInfoAtIndex(uint32_t idx, SBProcessInfo &info);
+
+  void Clear();
+
+private:
+  friend SBPlatform;
+
+  SBProcessInfoList(const lldb_private::ProcessInfoList &impl);
+  std::unique_ptr<lldb_private::ProcessInfoList> m_opaque_up;
+};
+
+} // namespace lldb
+
+#endif // LLDB_API_SBPROCESSINSTANCEINFOLIST_H
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index 08a58c80ef84779..129e4565d9ff993 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -407,6 +407,8 @@ class Platform : public PluginInterface {
   virtual uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info,
                                  ProcessInstanceInfoList &proc_infos);
 
+  ProcessInstanceInfoList GetAllProcesses();
+
   virtual bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info);
 
   // Set a breakpoint on all functions that can end up creating a thread for
@@ -883,7 +885,7 @@ class Platform : public PluginInterface {
   }
 
   virtual CompilerType GetSiginfoType(const llvm::Triple &triple);
-  
+
   virtual Args GetExtraStartupCommands();
 
   typedef std::function<Status(const ModuleSpec &module_spec,
diff --git a/lldb/include/lldb/Utility/ProcessInfo.h b/lldb/include/lldb/Utility/ProcessInfo.h
index f56b30ab82ec669..7fb5b37be0f48f1 100644
--- a/lldb/include/lldb/Utility/ProcessInfo.h
+++ b/lldb/include/lldb/Utility/ProcessInfo.h
@@ -187,6 +187,26 @@ class ProcessInstanceInfo : public ProcessInfo {
 
 typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
 
+class ProcessInfoList {
+public:
+  ProcessInfoList(const ProcessInstanceInfoList &list) : m_list(list) {}
+
+  uint32_t GetSize() const { return m_list.size(); }
+
+  bool GetProcessInfoAtIndex(uint32_t idx, ProcessInstanceInfo &info) {
+    if (idx < m_list.size()) {
+      info = m_list[idx];
+      return true;
+    }
+    return false;
+  }
+
+  void Clear() { return m_list.clear(); }
+
+private:
+  ProcessInstanceInfoList m_list;
+};
+
 // ProcessInstanceInfoMatch
 //
 // A class to help matching one ProcessInstanceInfo to another.
diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt
index 7cfa3aaafdae188..fb10d764be02c94 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -61,6 +61,7 @@ add_lldb_library(liblldb SHARED ${option_framework}
   SBPlatform.cpp
   SBProcess.cpp
   SBProcessInfo.cpp
+  SBProcessInfoList.cpp
   SBQueue.cpp
   SBQueueItem.cpp
   SBReproducer.cpp
diff --git a/lldb/source/API/SBPlatform.cpp b/lldb/source/API/SBPlatform.cpp
index c31848fe04ea72c..3623fd35bcdf13f 100644
--- a/lldb/source/API/SBPlatform.cpp
+++ b/lldb/source/API/SBPlatform.cpp
@@ -14,6 +14,7 @@
 #include "lldb/API/SBLaunchInfo.h"
 #include "lldb/API/SBModuleSpec.h"
 #include "lldb/API/SBPlatform.h"
+#include "lldb/API/SBProcessInfoList.h"
 #include "lldb/API/SBTarget.h"
 #include "lldb/API/SBUnixSignals.h"
 #include "lldb/Host/File.h"
@@ -599,6 +600,20 @@ SBProcess SBPlatform::Attach(SBAttachInfo &attach_info,
   return {};
 }
 
+SBProcessInfoList SBPlatform::GetAllProcesses(SBError &error) {
+  if (PlatformSP platform_sp = GetSP()) {
+    if (platform_sp->IsConnected()) {
+      ProcessInstanceInfoList list = platform_sp->GetAllProcesses();
+      return SBProcessInfoList(list);
+    }
+    error.SetErrorString("not connected");
+    return {};
+  }
+
+  error.SetErrorString("invalid platform");
+  return {};
+}
+
 SBError SBPlatform::Kill(const lldb::pid_t pid) {
   LLDB_INSTRUMENT_VA(this, pid);
   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
diff --git a/lldb/source/API/SBProcessInfoList.cpp b/lldb/source/API/SBProcessInfoList.cpp
new file mode 100644
index 000000000000000..a4d1e353f27d90e
--- /dev/null
+++ b/lldb/source/API/SBProcessInfoList.cpp
@@ -0,0 +1,73 @@
+//===-- SBProcessInfoList.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/API/SBProcessInfoList.h"
+#include "Utils.h"
+#include "lldb/API/SBProcessInfo.h"
+#include "lldb/Utility/Instrumentation.h"
+#include "lldb/Utility/ProcessInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBProcessInfoList::SBProcessInfoList() = default;
+
+SBProcessInfoList::~SBProcessInfoList() = default;
+
+SBProcessInfoList::SBProcessInfoList(const ProcessInfoList &impl)
+    : m_opaque_up(std::make_unique<ProcessInfoList>(impl)) {
+  LLDB_INSTRUMENT_VA(this, impl);
+}
+
+SBProcessInfoList::SBProcessInfoList(const lldb::SBProcessInfoList &rhs) {
+
+  LLDB_INSTRUMENT_VA(this, rhs);
+
+  m_opaque_up = clone(rhs.m_opaque_up);
+}
+
+const lldb::SBProcessInfoList &
+SBProcessInfoList::operator=(const lldb::SBProcessInfoList &rhs) {
+
+  LLDB_INSTRUMENT_VA(this, rhs);
+
+  if (this != &rhs)
+    m_opaque_up = clone(rhs.m_opaque_up);
+  return *this;
+}
+
+uint32_t SBProcessInfoList::GetSize() const {
+  LLDB_INSTRUMENT_VA(this);
+
+  if (m_opaque_up)
+    return m_opaque_up->GetSize();
+
+  return 0;
+}
+
+void SBProcessInfoList::Clear() {
+  LLDB_INSTRUMENT_VA(this);
+
+  if (m_opaque_up)
+    m_opaque_up->Clear();
+}
+
+bool SBProcessInfoList::GetProcessInfoAtIndex(uint32_t idx,
+                                              SBProcessInfo &info) {
+  LLDB_INSTRUMENT_VA(this, idx, info);
+
+  if (m_opaque_up) {
+    lldb_private::ProcessInstanceInfo process_instance_info;
+    if (m_opaque_up->GetProcessInfoAtIndex(idx, process_instance_info)) {
+      info.SetProcessInfo(process_instance_info);
+      return true;
+    }
+  }
+
+  return false;
+}
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index c117339f07cc9df..c345e33136070f2 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -989,6 +989,14 @@ uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch &match_info,
   return match_count;
 }
 
+ProcessInstanceInfoList Platform::GetAllProcesses() {
+  ProcessInstanceInfoList processes;
+  ProcessInstanceInfoMatch match;
+  assert(match.MatchAllProcesses());
+  FindProcesses(match, processes);
+  return processes;
+}
+
 Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) {
   Status error;
   Log *log = GetLog(LLDBLog::Platform);
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestPlatformListProcesses.py b/lldb/test/API/functionalities/gdb_remote_client/TestPlatformListProcesses.py
new file mode 100644
index 000000000000000..be0e3f5f8c50112
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestPlatformListProcesses.py
@@ -0,0 +1,54 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test.gdbclientutils import *
+from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
+
+
+class TestPlatformListProcesses(GDBRemoteTestBase):
+    @skipIfRemote
+    @skipIfWindows
+    def test_get_all_processes(self):
+        """Test listing processes"""
+
+        class MyPlatformResponder(MockGDBServerResponder):
+            def __init__(self):
+                MockGDBServerResponder.__init__(self)
+                self.done = False
+
+            def qfProcessInfo(self, packet):
+                return "pid:95117;name:666f6f;"
+
+            def qsProcessInfo(self):
+                if not self.done:
+                    self.done = True
+                    return "pid:95126;name:666f6f;"
+                return "E10"
+
+        self.server.responder = MyPlatformResponder()
+
+        error = lldb.SBError()
+        platform = lldb.SBPlatform("remote-linux")
+        self.dbg.SetSelectedPlatform(platform)
+
+        error = platform.ConnectRemote(
+            lldb.SBPlatformConnectOptions(self.server.get_connect_url())
+        )
+        self.assertSuccess(error)
+        self.assertTrue(platform.IsConnected())
+
+        processes = platform.GetAllProcesses(error)
+        self.assertSuccess(error)
+        self.assertEqual(processes.GetSize(), 2)
+        self.assertEqual(len(processes), 2)
+
+        process_info = lldb.SBProcessInfo()
+        processes.GetProcessInfoAtIndex(0, process_info)
+        self.assertEqual(process_info.GetProcessID(), 95117)
+        self.assertEqual(process_info.GetName(), "foo")
+
+        processes.GetProcessInfoAtIndex(1, process_info)
+        self.assertEqual(process_info.GetProcessID(), 95126)
+        self.assertEqual(process_info.GetName(), "foo")
+
+        platform.DisconnectRemote()



More information about the lldb-commits mailing list