enlight created this revision.
Herald added a subscriber: mgorny.

Implement `SBProcessInfo` to wrap `lldb_private::ProcessInstanceInfo`, and add 
`SBProcess::GetProcessInfo()` to retrieve info like parent ID, group ID, user 
ID etc. from a live process.


Repository:
  rL LLVM

https://reviews.llvm.org/D35881

Files:
  include/lldb/API/LLDB.h
  include/lldb/API/SBDefines.h
  include/lldb/API/SBFileSpec.h
  include/lldb/API/SBProcess.h
  include/lldb/API/SBProcessInfo.h
  
packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py
  
packages/Python/lldbsuite/test/python_api/default-constructor/sb_process_info.py
  packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py
  scripts/interface/SBProcess.i
  scripts/interface/SBProcessInfo.i
  scripts/lldb.swig
  source/API/CMakeLists.txt
  source/API/SBProcess.cpp
  source/API/SBProcessInfo.cpp

Index: source/API/SBProcessInfo.cpp
===================================================================
--- /dev/null
+++ source/API/SBProcessInfo.cpp
@@ -0,0 +1,145 @@
+//===-- SBProcessInfo.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBProcessInfo.h"
+
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBProcessInfo::SBProcessInfo() : m_opaque_ap() {}
+
+SBProcessInfo::SBProcessInfo(const SBProcessInfo &rhs) : m_opaque_ap() {
+  if (rhs.IsValid()) {
+    ref() = *rhs.m_opaque_ap;
+  }
+}
+
+SBProcessInfo::~SBProcessInfo() {}
+
+SBProcessInfo &SBProcessInfo::operator=(const SBProcessInfo &rhs) {
+  if (this != &rhs) {
+    if (rhs.IsValid())
+      ref() = *rhs.m_opaque_ap;
+    else
+      m_opaque_ap.reset();
+  }
+  return *this;
+}
+
+ProcessInstanceInfo &SBProcessInfo::ref() {
+  if (m_opaque_ap.get() == nullptr) {
+    m_opaque_ap.reset(new ProcessInstanceInfo());
+  }
+  return *m_opaque_ap;
+}
+
+void SBProcessInfo::SetProcessInfo(const ProcessInstanceInfo &proc_info_ref) {
+  ref() = proc_info_ref;
+}
+
+bool SBProcessInfo::IsValid() const { return m_opaque_ap.get() != nullptr; }
+
+const char *SBProcessInfo::GetName() {
+  const char *name = nullptr;
+  if (m_opaque_ap) {
+    name = m_opaque_ap->GetName();
+  }
+  return name;
+}
+
+SBFileSpec SBProcessInfo::GetExecutableFile() {
+  SBFileSpec file_spec;
+  if (m_opaque_ap) {
+    file_spec.SetFileSpec(m_opaque_ap->GetExecutableFile());
+  }
+  return file_spec;
+}
+
+lldb::pid_t SBProcessInfo::GetProcessID() {
+  lldb::pid_t proc_id = LLDB_INVALID_PROCESS_ID;
+  if (m_opaque_ap) {
+    proc_id = m_opaque_ap->GetProcessID();
+  }
+  return proc_id;
+}
+
+uint32_t SBProcessInfo::GetUserID() {
+  uint32_t user_id = UINT32_MAX;
+  if (m_opaque_ap) {
+    user_id = m_opaque_ap->GetUserID();
+  }
+  return user_id;
+}
+
+uint32_t SBProcessInfo::GetGroupID() {
+  uint32_t group_id = UINT32_MAX;
+  if (m_opaque_ap) {
+    group_id = m_opaque_ap->GetGroupID();
+  }
+  return group_id;
+}
+
+bool SBProcessInfo::UserIDIsValid() {
+  bool is_valid = false;
+  if (m_opaque_ap) {
+    is_valid = m_opaque_ap->UserIDIsValid();
+  }
+  return is_valid;
+}
+
+bool SBProcessInfo::GroupIDIsValid() {
+  bool is_valid = false;
+  if (m_opaque_ap) {
+    is_valid = m_opaque_ap->GroupIDIsValid();
+  }
+  return is_valid;
+}
+
+uint32_t SBProcessInfo::GetEffectiveUserID() {
+  uint32_t user_id = UINT32_MAX;
+  if (m_opaque_ap) {
+    user_id = m_opaque_ap->GetEffectiveUserID();
+  }
+  return user_id;
+}
+
+uint32_t SBProcessInfo::GetEffectiveGroupID() {
+  uint32_t group_id = UINT32_MAX;
+  if (m_opaque_ap) {
+    group_id = m_opaque_ap->GetEffectiveGroupID();
+  }
+  return group_id;
+}
+
+bool SBProcessInfo::EffectiveUserIDIsValid() {
+  bool is_valid = false;
+  if (m_opaque_ap) {
+    is_valid = m_opaque_ap->EffectiveUserIDIsValid();
+  }
+  return is_valid;
+}
+
+bool SBProcessInfo::EffectiveGroupIDIsValid() {
+  bool is_valid = false;
+  if (m_opaque_ap) {
+    is_valid = m_opaque_ap->EffectiveGroupIDIsValid();
+  }
+  return is_valid;
+}
+
+lldb::pid_t SBProcessInfo::GetParentProcessID() {
+  lldb::pid_t proc_id = LLDB_INVALID_PROCESS_ID;
+  if (m_opaque_ap) {
+    proc_id = m_opaque_ap->GetParentProcessID();
+  }
+  return proc_id;
+}
Index: source/API/SBProcess.cpp
===================================================================
--- source/API/SBProcess.cpp
+++ source/API/SBProcess.cpp
@@ -1369,3 +1369,13 @@
   }
   return sb_region_list;
 }
+
+lldb::SBProcessInfo SBProcess::GetProcessInfo() {
+  lldb::SBProcessInfo sb_proc_info;
+  ProcessSP process_sp(GetSP());
+  ProcessInstanceInfo proc_info;
+  if (process_sp && process_sp->GetProcessInfo(proc_info)) {
+    sb_proc_info.SetProcessInfo(proc_info);
+  }
+  return sb_proc_info;
+}
Index: source/API/CMakeLists.txt
===================================================================
--- source/API/CMakeLists.txt
+++ source/API/CMakeLists.txt
@@ -53,6 +53,7 @@
   SBModuleSpec.cpp
   SBPlatform.cpp
   SBProcess.cpp
+  SBProcessInfo.cpp
   SBQueue.cpp
   SBQueueItem.cpp
   SBSection.cpp
Index: scripts/lldb.swig
===================================================================
--- scripts/lldb.swig
+++ scripts/lldb.swig
@@ -111,6 +111,7 @@
 #include "lldb/API/SBModuleSpec.h"
 #include "lldb/API/SBPlatform.h"
 #include "lldb/API/SBProcess.h"
+#include "lldb/API/SBProcessInfo.h"
 #include "lldb/API/SBQueue.h"
 #include "lldb/API/SBQueueItem.h"
 #include "lldb/API/SBSection.h"
@@ -196,6 +197,7 @@
 %include "./interface/SBModuleSpec.i"
 %include "./interface/SBPlatform.i"
 %include "./interface/SBProcess.i"
+%include "./interface/SBProcessInfo.i"
 %include "./interface/SBQueue.i"
 %include "./interface/SBQueueItem.i"
 %include "./interface/SBSection.i"
Index: scripts/interface/SBProcessInfo.i
===================================================================
--- /dev/null
+++ scripts/interface/SBProcessInfo.i
@@ -0,0 +1,66 @@
+//===-- SWIG Interface for SBProcessInfo-------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+namespace lldb {
+
+%feature("docstring",
+"Describes an existing process and any discoverable information that pertains to
+that process."
+) SBProcessInfo;
+
+class SBProcessInfo
+{
+public:
+    SBProcessInfo();
+
+    SBProcessInfo (const SBProcessInfo &rhs);
+
+    ~SBProcessInfo ();
+
+    bool
+    IsValid ();
+
+    const char *
+    GetName ();
+
+    SBFileSpec
+    GetExecutableFile ();
+
+    lldb::pid_t
+    GetProcessID ();
+
+    uint32_t
+    GetUserID ();
+
+    uint32_t
+    GetGroupID ();
+
+    bool
+    UserIDIsValid ();
+
+    bool
+    GroupIDIsValid ();
+
+    uint32_t
+    GetEffectiveUserID ();
+
+    uint32_t
+    GetEffectiveGroupID ();
+
+    bool
+    EffectiveUserIDIsValid ();
+
+    bool
+    EffectiveGroupIDIsValid ();
+
+    lldb::pid_t
+    GetParentProcessID ();
+};
+
+} // namespace lldb
Index: scripts/interface/SBProcess.i
===================================================================
--- scripts/interface/SBProcess.i
+++ scripts/interface/SBProcess.i
@@ -417,6 +417,18 @@
     lldb::SBMemoryRegionInfoList
     GetMemoryRegions();
 
+    %feature("autodoc", "
+    Get information about the process.
+    Valid process info will only be returned when the process is alive,
+    use IsValid() to check if the info returned is valid.
+
+    process_info = process.GetProcessInfo()
+    if process_info.IsValid():
+        process_info.GetProcessID()
+    ") GetProcessInfo;
+    lldb::SBProcessInfo
+    GetProcessInfo();
+
     %pythoncode %{
         def __get_is_alive__(self):
             '''Returns "True" if the process is currently alive, "False" otherwise'''
Index: packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py
===================================================================
--- packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py
+++ packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py
@@ -325,3 +325,66 @@
         num = process.GetNumSupportedHardwareWatchpoints(error)
         if self.TraceOn() and error.Success():
             print("Number of supported hardware watchpoints: %d" % num)
+
+    @add_test_categories(['pyapi'])
+    @no_debug_info_test
+    def test_get_process_info(self):
+        """Test SBProcess::GetProcessInfo() API with a locally launched process."""
+        self.build()
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        # Launch the process and stop at the entry point.
+        launch_info = lldb.SBLaunchInfo(None)
+        launch_info.SetWorkingDirectory(self.get_process_working_directory())
+        launch_flags = launch_info.GetLaunchFlags()
+        launch_flags |= lldb.eLaunchFlagStopAtEntry
+        launch_info.SetLaunchFlags(launch_flags)
+        error = lldb.SBError()
+        process = target.Launch(launch_info, error)
+
+        if not error.Success():
+            self.fail("Failed to launch process")
+
+        # Verify all process info can be retrieved successfully
+        process_info = process.GetProcessInfo()
+        self.assertTrue(process_info.IsValid())
+        file_spec = process_info.GetExecutableFile()
+        self.assertTrue(file_spec.IsValid())
+        process_name = process_info.GetName()
+        self.assertIsNotNone(process_name, "Process has a name")
+        self.assertGreater(len(process_name), 0, "Process name isn't blank")
+        self.assertEqual(file_spec.GetFilename(), "a.out")
+        self.assertNotEqual(
+            process_info.GetProcessID(), lldb.LLDB_INVALID_PROCESS_ID,
+            "Process ID is valid")
+
+        if self.getPlatform() != 'windows':
+            self.assertTrue(process_info.UserIDIsValid())
+            self.assertNotEqual(
+                process_info.GetUserID(), lldb.UINT32_MAX,
+                "Process user ID is valid")
+            self.assertTrue(process_info.GroupIDIsValid())
+            self.assertNotEqual(
+                process_info.GetGroupID(), lldb.UINT32_MAX,
+                "Process group ID is valid")
+            self.assertTrue(process_info.EffectiveUserIDIsValid())
+            self.assertNotEqual(
+                process_info.GetEffectiveUserID(), lldb.UINT32_MAX,
+                "Process effective user ID is valid")
+            self.assertTrue(process_info.EffectiveGroupIDIsValid())
+            self.assertNotEqual(
+                process_info.GetEffectiveGroupID(), lldb.UINT32_MAX,
+                "Process effective group ID is valid")
+            self.assertNotEqual(
+                process_info.GetParentProcessID(), lldb.LLDB_INVALID_PROCESS_ID,
+                "Parent process ID is valid"
+            )
+
+        # Verify that a dead process doesn't yield stale process info
+        process.Kill()
+        process_info = process.GetProcessInfo()
+        self.assertFalse(process_info.IsValid())
Index: packages/Python/lldbsuite/test/python_api/default-constructor/sb_process_info.py
===================================================================
--- /dev/null
+++ packages/Python/lldbsuite/test/python_api/default-constructor/sb_process_info.py
@@ -0,0 +1,22 @@
+"""
+Fuzz tests an object after the default construction to make sure it does not crash lldb.
+"""
+
+import sys
+import lldb
+
+
+def fuzz_obj(obj):
+    obj.IsValid()
+    obj.GetName()
+    obj.GetExecutableFile()
+    obj.GetProcessID()
+    obj.GetUserID()
+    obj.GetGroupID()
+    obj.UserIDIsValid()
+    obj.GroupIDIsValid()
+    obj.GetEffectiveUserID()
+    obj.GetEffectiveGroupID()
+    obj.EffectiveUserIDIsValid()
+    obj.EffectiveGroupIDIsValid()
+    obj.GetParentProcessID()
Index: packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py
===================================================================
--- packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py
+++ packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py
@@ -255,6 +255,17 @@
 
     @add_test_categories(['pyapi'])
     @no_debug_info_test
+    def test_SBProcessInfo(self):
+        obj = lldb.SBProcessInfo()
+        if self.TraceOn():
+            print(obj)
+        self.assertFalse(obj)
+        # Do fuzz testing on the invalid obj, it should not crash lldb.
+        import sb_process_info
+        sb_process_info.fuzz_obj(obj)
+
+    @add_test_categories(['pyapi'])
+    @no_debug_info_test
     def test_SBSection(self):
         obj = lldb.SBSection()
         if self.TraceOn():
Index: include/lldb/API/SBProcessInfo.h
===================================================================
--- /dev/null
+++ include/lldb/API/SBProcessInfo.h
@@ -0,0 +1,64 @@
+//===-- SBProcessInfo.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBProcessInfo_h_
+#define LLDB_SBProcessInfo_h_
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+
+class LLDB_API SBProcessInfo {
+public:
+  SBProcessInfo();
+  SBProcessInfo(const SBProcessInfo &rhs);
+
+  ~SBProcessInfo();
+
+  SBProcessInfo &operator=(const SBProcessInfo &rhs);
+
+  bool IsValid() const;
+
+  const char *GetName();
+
+  SBFileSpec GetExecutableFile();
+
+  lldb::pid_t GetProcessID();
+
+  uint32_t GetUserID();
+
+  uint32_t GetGroupID();
+
+  bool UserIDIsValid();
+
+  bool GroupIDIsValid();
+
+  uint32_t GetEffectiveUserID();
+
+  uint32_t GetEffectiveGroupID();
+
+  bool EffectiveUserIDIsValid();
+
+  bool EffectiveGroupIDIsValid();
+
+  lldb::pid_t GetParentProcessID();
+
+private:
+  friend class SBProcess;
+
+  lldb_private::ProcessInstanceInfo &ref();
+
+  void SetProcessInfo(const lldb_private::ProcessInstanceInfo &proc_info_ref);
+
+  std::unique_ptr<lldb_private::ProcessInstanceInfo> m_opaque_ap;
+};
+
+} // namespace lldb
+
+#endif // LLDB_SBProcessInfo_h_
Index: include/lldb/API/SBProcess.h
===================================================================
--- include/lldb/API/SBProcess.h
+++ include/lldb/API/SBProcess.h
@@ -12,6 +12,7 @@
 
 #include "lldb/API/SBDefines.h"
 #include "lldb/API/SBError.h"
+#include "lldb/API/SBProcessInfo.h"
 #include "lldb/API/SBQueue.h"
 #include "lldb/API/SBTarget.h"
 #include <stdio.h>
@@ -380,6 +381,15 @@
   //------------------------------------------------------------------
   lldb::SBMemoryRegionInfoList GetMemoryRegions();
 
+  //------------------------------------------------------------------
+  /// Return information about the process.
+  ///
+  /// Valid process info will only be returned when the process is
+  /// alive, use SBProcessInfo::IsValid() to check returned info is
+  /// valid.
+  //------------------------------------------------------------------
+  lldb::SBProcessInfo GetProcessInfo();
+
 protected:
   friend class SBAddress;
   friend class SBBreakpoint;
Index: include/lldb/API/SBFileSpec.h
===================================================================
--- include/lldb/API/SBFileSpec.h
+++ include/lldb/API/SBFileSpec.h
@@ -65,6 +65,7 @@
   friend class SBModuleSpec;
   friend class SBPlatform;
   friend class SBProcess;
+  friend class SBProcessInfo;
   friend class SBSourceManager;
   friend class SBThread;
   friend class SBTarget;
Index: include/lldb/API/SBDefines.h
===================================================================
--- include/lldb/API/SBDefines.h
+++ include/lldb/API/SBDefines.h
@@ -65,6 +65,7 @@
 class LLDB_API SBModuleSpec;
 class LLDB_API SBModuleSpecList;
 class LLDB_API SBProcess;
+class LLDB_API SBProcessInfo;
 class LLDB_API SBQueue;
 class LLDB_API SBQueueItem;
 class LLDB_API SBSection;
Index: include/lldb/API/LLDB.h
===================================================================
--- include/lldb/API/LLDB.h
+++ include/lldb/API/LLDB.h
@@ -49,6 +49,7 @@
 #include "lldb/API/SBModuleSpec.h"
 #include "lldb/API/SBPlatform.h"
 #include "lldb/API/SBProcess.h"
+#include "lldb/API/SBProcessInfo.h"
 #include "lldb/API/SBQueue.h"
 #include "lldb/API/SBQueueItem.h"
 #include "lldb/API/SBSection.h"
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to