Index: include/lldb/API/SBDebugger.h =================================================================== --- include/lldb/API/SBDebugger.h +++ include/lldb/API/SBDebugger.h @@ -131,6 +131,25 @@ lldb::SBPlatform GetSelectedPlatform(); void SetSelectedPlatform(lldb::SBPlatform &platform); + + /// Get the number of currently active platforms. + uint32_t GetNumPlatforms(); + + /// Get one of the currently active platforms. + lldb::SBPlatform GetPlatformAtIndex(uint32_t idx); + + /// Get the number of available platforms. + /// + /// The return value should match the number of entries output by the + /// "platform list" command. + uint32_t GetNumAvailablePlatforms(); + + /// Get the name and description of one of the available platforms. + /// + /// @param[in] idx + /// Zero-based index of the platform for which info should be retrieved, + /// must be less than the value returned by GetNumAvailablePlatforms(). + lldb::SBStructuredData GetAvailablePlatformInfoAtIndex(uint32_t idx); lldb::SBSourceManager GetSourceManager(); Index: include/lldb/API/SBStructuredData.h =================================================================== --- include/lldb/API/SBStructuredData.h +++ include/lldb/API/SBStructuredData.h @@ -98,6 +98,7 @@ protected: friend class SBTraceOptions; + friend class SBDebugger; StructuredDataImplUP m_impl_up; }; Index: packages/Python/lldbsuite/test/functionalities/platform/TestPlatformPython.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/platform/TestPlatformPython.py @@ -0,0 +1,70 @@ +""" +Test the lldb platform Python API. +""" + +from __future__ import print_function + + +import os +import time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class PlatformPythonTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_platform_list(self): + """Test SBDebugger::GetNumPlatforms() & GetPlatformAtIndex() API""" + # Verify there's only the host platform present by default. + self.assertEqual(self.dbg.GetNumPlatforms(), 1) + host_platform = self.dbg.GetPlatformAtIndex(0) + self.assertTrue(host_platform.IsValid() and + host_platform.GetName() == 'host', + 'Only the host platform is available') + # Select another platform and verify that the platform is added to + # the platform list. + platform_idx = self.dbg.GetNumAvailablePlatforms() - 1 + if platform_idx < 1: + self.fail('No platforms other than host are available') + platform_data = self.dbg.GetAvailablePlatformInfoAtIndex(platform_idx) + platform_name = platform_data.GetValueForKey('name').GetStringValue(100) + self.assertNotEqual(platform_name, 'host') + self.dbg.SetCurrentPlatform(platform_name) + selected_platform = self.dbg.GetSelectedPlatform() + self.assertTrue(selected_platform.IsValid()) + self.assertEqual(selected_platform.GetName(), platform_name) + self.assertEqual(self.dbg.GetNumPlatforms(), 2) + platform = self.dbg.GetPlatformAtIndex(1) + self.assertEqual(platform.GetName(), platform_name) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_available_platform_list(self): + """Test SBDebugger::GetNumAvailablePlatforms() and GetAvailablePlatformInfoAtIndex() API""" + num_platforms = self.dbg.GetNumAvailablePlatforms() + self.assertGreater( + num_platforms, 0, + 'There should be at least one platform available') + + for i in range(num_platforms): + platform_data = self.dbg.GetAvailablePlatformInfoAtIndex(i) + name_data = platform_data.GetValueForKey('name') + desc_data = platform_data.GetValueForKey('description') + self.assertTrue( + name_data and name_data.IsValid(), + 'Platform has a name') + self.assertEqual( + name_data.GetType(), lldb.eStructuredDataTypeString, + 'Platform name is a string') + self.assertTrue( + desc_data and desc_data.IsValid(), + 'Platform has a description') + self.assertEqual( + desc_data.GetType(), lldb.eStructuredDataTypeString, + 'Platform description is a string') Index: packages/Python/lldbsuite/test/python_api/default-constructor/sb_debugger.py =================================================================== --- packages/Python/lldbsuite/test/python_api/default-constructor/sb_debugger.py +++ packages/Python/lldbsuite/test/python_api/default-constructor/sb_debugger.py @@ -30,6 +30,10 @@ obj.FindTargetWithFileAndArch("a.out", "arm") obj.GetNumTargets() obj.GetSelectedTarget() + obj.GetNumPlatforms() + obj.GetPlatformAtIndex(0xffffffff) + obj.GetNumAvailablePlatforms() + obj.GetAvailablePlatformInfoAtIndex(0xffffffff) obj.GetSourceManager() obj.SetSelectedTarget(lldb.SBTarget()) obj.SetCurrentPlatformSDKRoot("tmp/sdk-root") Index: scripts/interface/SBDebugger.i =================================================================== --- scripts/interface/SBDebugger.i +++ scripts/interface/SBDebugger.i @@ -247,6 +247,34 @@ void SetSelectedPlatform(lldb::SBPlatform &platform); + %feature("docstring", + "Get the number of currently active platforms." + ) GetNumPlatforms; + uint32_t + GetNumPlatforms (); + + %feature("docstring", + "Get one of the currently active platforms." + ) GetPlatformAtIndex; + lldb::SBPlatform + GetPlatformAtIndex (uint32_t idx); + + %feature("docstring", + "Get the number of available platforms." + ) GetNumAvailablePlatforms; + uint32_t + GetNumAvailablePlatforms (); + + %feature("docstring", " + Get the name and description of one of the available platforms. + + @param idx Zero-based index of the platform for which info should be + retrieved, must be less than the value returned by + GetNumAvailablePlatforms(). + ") GetAvailablePlatformInfoAtIndex; + lldb::SBStructuredData + GetAvailablePlatformInfoAtIndex (uint32_t idx); + lldb::SBSourceManager GetSourceManager (); Index: source/API/SBDebugger.cpp =================================================================== --- source/API/SBDebugger.cpp +++ source/API/SBDebugger.cpp @@ -26,6 +26,7 @@ #include "lldb/API/SBSourceManager.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" +#include "lldb/API/SBStructuredData.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" #include "lldb/API/SBTypeCategory.h" @@ -37,8 +38,10 @@ #include "lldb/API/SystemInitializerFull.h" #include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Initialization/SystemLifetimeManager.h" #include "lldb/Interpreter/Args.h" @@ -774,6 +777,67 @@ sb_platform.GetName()); } +uint32_t SBDebugger::GetNumPlatforms() { + if (m_opaque_sp) { + // No need to lock, the platform list is thread safe + return m_opaque_sp->GetPlatformList().GetSize(); + } + return 0; +} + +SBPlatform SBDebugger::GetPlatformAtIndex(uint32_t idx) { + SBPlatform sb_platform; + if (m_opaque_sp) { + // No need to lock, the platform list is thread safe + sb_platform.SetSP(m_opaque_sp->GetPlatformList().GetAtIndex(idx)); + } + return sb_platform; +} + +uint32_t SBDebugger::GetNumAvailablePlatforms() { + uint32_t idx = 0; + while (true) { + if (!PluginManager::GetPlatformPluginNameAtIndex(idx)) { + break; + } + ++idx; + } + // +1 for the host platform, which should always appear first in the list. + return idx + 1; +} + +SBStructuredData SBDebugger::GetAvailablePlatformInfoAtIndex(uint32_t idx) { + SBStructuredData data; + auto platform_dict = llvm::make_unique(); + llvm::StringRef name_str("name"), desc_str("description"); + + if (idx == 0) { + PlatformSP host_platform_sp(Platform::GetHostPlatform()); + platform_dict->AddStringItem( + name_str, host_platform_sp->GetPluginName().GetStringRef()); + platform_dict->AddStringItem( + desc_str, llvm::StringRef(host_platform_sp->GetDescription())); + } else if (idx > 0) { + const char *plugin_name = + PluginManager::GetPlatformPluginNameAtIndex(idx - 1); + if (!plugin_name) { + return data; + } + platform_dict->AddStringItem(name_str, llvm::StringRef(plugin_name)); + + const char *plugin_desc = + PluginManager::GetPlatformPluginDescriptionAtIndex(idx - 1); + if (!plugin_desc) { + return data; + } + platform_dict->AddStringItem(desc_str, llvm::StringRef(plugin_desc)); + } + + data.m_impl_up->SetObjectSP( + StructuredData::ObjectSP(platform_dict.release())); + return data; +} + void SBDebugger::DispatchInput(void *baton, const void *data, size_t data_len) { DispatchInput(data, data_len); }