Index: lldb/trunk/include/lldb/API/LLDB.h =================================================================== --- lldb/trunk/include/lldb/API/LLDB.h +++ lldb/trunk/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" Index: lldb/trunk/include/lldb/API/SBDefines.h =================================================================== --- lldb/trunk/include/lldb/API/SBDefines.h +++ lldb/trunk/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: lldb/trunk/include/lldb/API/SBFileSpec.h =================================================================== --- lldb/trunk/include/lldb/API/SBFileSpec.h +++ lldb/trunk/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: lldb/trunk/include/lldb/API/SBProcess.h =================================================================== --- lldb/trunk/include/lldb/API/SBProcess.h +++ lldb/trunk/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 @@ -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: lldb/trunk/include/lldb/API/SBProcessInfo.h =================================================================== --- lldb/trunk/include/lldb/API/SBProcessInfo.h +++ lldb/trunk/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 m_opaque_ap; +}; + +} // namespace lldb + +#endif // LLDB_SBProcessInfo_h_ Index: lldb/trunk/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py +++ lldb/trunk/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: lldb/trunk/packages/Python/lldbsuite/test/python_api/default-constructor/sb_process_info.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/python_api/default-constructor/sb_process_info.py +++ lldb/trunk/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: lldb/trunk/packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py +++ lldb/trunk/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: lldb/trunk/scripts/interface/SBProcess.i =================================================================== --- lldb/trunk/scripts/interface/SBProcess.i +++ lldb/trunk/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: lldb/trunk/scripts/interface/SBProcessInfo.i =================================================================== --- lldb/trunk/scripts/interface/SBProcessInfo.i +++ lldb/trunk/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: lldb/trunk/scripts/lldb.swig =================================================================== --- lldb/trunk/scripts/lldb.swig +++ lldb/trunk/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: lldb/trunk/source/API/CMakeLists.txt =================================================================== --- lldb/trunk/source/API/CMakeLists.txt +++ lldb/trunk/source/API/CMakeLists.txt @@ -53,6 +53,7 @@ SBModuleSpec.cpp SBPlatform.cpp SBProcess.cpp + SBProcessInfo.cpp SBQueue.cpp SBQueueItem.cpp SBSection.cpp Index: lldb/trunk/source/API/SBProcess.cpp =================================================================== --- lldb/trunk/source/API/SBProcess.cpp +++ lldb/trunk/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: lldb/trunk/source/API/SBProcessInfo.cpp =================================================================== --- lldb/trunk/source/API/SBProcessInfo.cpp +++ lldb/trunk/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; +}