Author: enrico Date: Wed Nov 4 18:46:25 2015 New Revision: 252112 URL: http://llvm.org/viewvc/llvm-project?rev=252112&view=rev Log: Teach LLDB how to directly launch processes on the iOS simulator
This allows for command-line debugging of iOS simulator binaries (as long as UI is not required, or a full UI simulator has previously been otherwise launched), as well as execution of the LLDB test suite on the iOS simulator This is known to compile on OSX 10.11 GM - feedback from people on other platforms and/or older versions of OSX as to the buildability of this code is greatly appreciated Added: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/packages/Python/lldbsuite/test/dotest.py lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/attach_denied/TestAttachDenied.py lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py lldb/trunk/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules lldb/trunk/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py lldb/trunk/source/Plugins/Platform/MacOSX/CMakeLists.txt lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Nov 4 18:46:25 2015 @@ -772,6 +772,8 @@ 945261C51B9A11FC00BF138D /* LibCxxVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BB1B9A11E800BF138D /* LibCxxVector.cpp */; }; 945261C61B9A11FC00BF138D /* LibStdcpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BC1B9A11E800BF138D /* LibStdcpp.cpp */; }; 945261C81B9A14D300BF138D /* CXXFunctionPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261C71B9A14D300BF138D /* CXXFunctionPointer.cpp */; }; + 9455630F1BEAD0600073F75F /* PlatformAppleSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9455630A1BEAD0570073F75F /* PlatformAppleSimulator.cpp */; }; + 945563101BEAD0650073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9455630D1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm */; }; 945759671534941F005A9070 /* PlatformPOSIX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945759651534941F005A9070 /* PlatformPOSIX.cpp */; }; 945E8D80152F6AB40019BCCD /* StreamGDBRemote.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945E8D7F152F6AB40019BCCD /* StreamGDBRemote.cpp */; }; 9461569A14E358A6003A195C /* SBTypeFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568A14E35621003A195C /* SBTypeFilter.cpp */; }; @@ -2523,6 +2525,10 @@ 945261BD1B9A11E800BF138D /* LibStdcpp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LibStdcpp.h; path = Language/CPlusPlus/LibStdcpp.h; sourceTree = "<group>"; }; 945261C71B9A14D300BF138D /* CXXFunctionPointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CXXFunctionPointer.cpp; path = source/DataFormatters/CXXFunctionPointer.cpp; sourceTree = "<group>"; }; 945261C91B9A14E000BF138D /* CXXFunctionPointer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CXXFunctionPointer.h; path = include/lldb/DataFormatters/CXXFunctionPointer.h; sourceTree = "<group>"; }; + 9455630A1BEAD0570073F75F /* PlatformAppleSimulator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformAppleSimulator.cpp; sourceTree = "<group>"; }; + 9455630B1BEAD0570073F75F /* PlatformAppleSimulator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformAppleSimulator.h; sourceTree = "<group>"; }; + 9455630C1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformiOSSimulatorCoreSimulatorSupport.h; sourceTree = "<group>"; }; + 9455630D1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformiOSSimulatorCoreSimulatorSupport.mm; sourceTree = "<group>"; }; 945759651534941F005A9070 /* PlatformPOSIX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformPOSIX.cpp; path = POSIX/PlatformPOSIX.cpp; sourceTree = "<group>"; }; 945759661534941F005A9070 /* PlatformPOSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformPOSIX.h; path = POSIX/PlatformPOSIX.h; sourceTree = "<group>"; }; 945E8D7D152F6AA80019BCCD /* StreamGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamGDBRemote.h; path = include/lldb/Core/StreamGDBRemote.h; sourceTree = "<group>"; }; @@ -4929,12 +4935,16 @@ 26C5577F132575C8008FD8FE /* MacOSX */ = { isa = PBXGroup; children = ( + 9455630A1BEAD0570073F75F /* PlatformAppleSimulator.cpp */, + 9455630B1BEAD0570073F75F /* PlatformAppleSimulator.h */, AF254E2F170CCC33007AE5C9 /* PlatformDarwinKernel.cpp */, AF254E30170CCC33007AE5C9 /* PlatformDarwinKernel.h */, 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */, 2697A54C133A6305004E4240 /* PlatformDarwin.h */, 26B7564C14F89356008D9CB3 /* PlatformiOSSimulator.cpp */, 26B7564D14F89356008D9CB3 /* PlatformiOSSimulator.h */, + 9455630C1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.h */, + 9455630D1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm */, 26C5577B132575AD008FD8FE /* PlatformMacOSX.cpp */, 26C5577C132575AD008FD8FE /* PlatformMacOSX.h */, 2675F6FE1332BE690067997B /* PlatformRemoteiOS.cpp */, @@ -6622,6 +6632,7 @@ 25EF23781AC09B3700908DF0 /* AdbClient.cpp in Sources */, 94380B8219940B0A00BFE4A8 /* StringLexer.cpp in Sources */, 268900C413353E5F00698AC0 /* DWARFDefines.cpp in Sources */, + 945563101BEAD0650073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm in Sources */, 268900C513353E5F00698AC0 /* DWARFDIECollection.cpp in Sources */, 268900C613353E5F00698AC0 /* DWARFFormValue.cpp in Sources */, 3FDFE53119A292F0009756A7 /* HostInfoPosix.cpp in Sources */, @@ -6877,6 +6888,7 @@ 260CC64A15D0440D002BF2E0 /* OptionValueBoolean.cpp in Sources */, 260CC64B15D0440D002BF2E0 /* OptionValueProperties.cpp in Sources */, 3FDFED0C19B7C8E7009756A7 /* ThisThread.cpp in Sources */, + 9455630F1BEAD0600073F75F /* PlatformAppleSimulator.cpp in Sources */, 6D86CEA01B440F8500A7FBFA /* CommandObjectBugreport.cpp in Sources */, 260CC64C15D0440D002BF2E0 /* OptionValueDictionary.cpp in Sources */, 49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */, Modified: lldb/trunk/packages/Python/lldbsuite/test/dotest.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/dotest.py?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/dotest.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/dotest.py Wed Nov 4 18:46:25 2015 @@ -1381,6 +1381,28 @@ def isMultiprocessTestRunner(): # test runner return not (is_inferior_test_runner or no_multiprocess_test_runner) +def getVersionForSDK(sdk): + sdk = str.lower(sdk) + full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk) + basename = os.path.basename(full_path) + basename = os.path.splitext(basename)[0] + basename = str.lower(basename) + ver = basename.replace(sdk, '') + return ver + +def getPathForSDK(sdk): + sdk = str.lower(sdk) + full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk) + if os.path.exists(full_path): return full_path + return None + +def setDefaultTripleForPlatform(): + if lldb_platform_name == 'ios-simulator': + triple_str = 'x86_64-apple-ios%s' % (getVersionForSDK('iphonesimulator')) + os.environ['TRIPLE'] = triple_str + return {'TRIPLE':triple_str} + return {} + def run_suite(): global just_do_benchmarks_test global dont_do_dsym_test @@ -1478,6 +1500,7 @@ def run_suite(): if lldb_platform_name: print("Setting up remote platform '%s'" % (lldb_platform_name)) lldb.remote_platform = lldb.SBPlatform(lldb_platform_name) + lldb.remote_platform_name = lldb_platform_name if not lldb.remote_platform.IsValid(): print("error: unable to create the LLDB platform named '%s'." % (lldb_platform_name)) exitTestSuite(1) @@ -1495,10 +1518,17 @@ def run_suite(): else: lldb.platform_url = None - if lldb_platform_working_dir: - print("Setting remote platform working directory to '%s'..." % (lldb_platform_working_dir)) - lldb.remote_platform.SetWorkingDirectory(lldb_platform_working_dir) - + platform_changes = setDefaultTripleForPlatform() + first = True + for key in platform_changes: + if first: + print("Environment variables setup for platform support:") + first = False + print("%s = %s" % (key,platform_changes[key])) + + if lldb_platform_working_dir: + print("Setting remote platform working directory to '%s'..." % (lldb_platform_working_dir)) + lldb.remote_platform.SetWorkingDirectory(lldb_platform_working_dir) lldb.remote_platform_working_dir = lldb_platform_working_dir lldb.DBG.SetSelectedPlatform(lldb.remote_platform) else: Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py Wed Nov 4 18:46:25 2015 @@ -17,6 +17,7 @@ class ProcessAttachTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) + @skipIfiOSSimulator def test_attach_to_process_by_id(self): """Test attach by process id""" self.build() Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/attach_denied/TestAttachDenied.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/attach_denied/TestAttachDenied.py?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/attach_denied/TestAttachDenied.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_attach/attach_denied/TestAttachDenied.py Wed Nov 4 18:46:25 2015 @@ -24,6 +24,7 @@ class AttachDeniedTestCase(TestBase): return (err, shell_command.GetStatus(), shell_command.GetOutput()) @skipIfWindows + @skipIfiOSSimulator def test_attach_to_process_by_id_denied(self): """Test attach by process id denied""" self.build() Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py Wed Nov 4 18:46:25 2015 @@ -24,6 +24,7 @@ class RegisterCommandsTestCase(TestBase) self.dbg.GetSelectedTarget().GetProcess().Destroy() TestBase.tearDown(self) + @skipIfiOSSimulator def test_register_commands(self): """Test commands related to registers, in particular vector registers.""" if not self.getArchitecture() in ['amd64', 'i386', 'x86_64']: @@ -31,6 +32,7 @@ class RegisterCommandsTestCase(TestBase) self.build() self.register_commands() + @skipIfiOSSimulator @skipIfTargetAndroid(archs=["i386"]) # Writing of mxcsr register fails, presumably due to a kernel/hardware problem def test_fp_register_write(self): """Test commands that write to registers, in particular floating-point registers.""" @@ -39,6 +41,7 @@ class RegisterCommandsTestCase(TestBase) self.build() self.fp_register_write() + @skipIfiOSSimulator @expectedFailureAndroid(archs=["i386"]) # "register read fstat" always return 0xffff @skipIfFreeBSD #llvm.org/pr25057 def test_fp_special_purpose_register_read(self): @@ -48,6 +51,7 @@ class RegisterCommandsTestCase(TestBase) self.build() self.fp_special_purpose_register_read() + @skipIfiOSSimulator def test_register_expressions(self): """Test expression evaluation with commands related to registers.""" if not self.getArchitecture() in ['amd64', 'i386', 'x86_64']: @@ -55,6 +59,7 @@ class RegisterCommandsTestCase(TestBase) self.build() self.register_expressions() + @skipIfiOSSimulator def test_convenience_registers(self): """Test convenience registers.""" if not self.getArchitecture() in ['amd64', 'x86_64']: @@ -62,6 +67,7 @@ class RegisterCommandsTestCase(TestBase) self.build() self.convenience_registers() + @skipIfiOSSimulator def test_convenience_registers_with_process_attach(self): """Test convenience registers after a 'process attach'.""" if not self.getArchitecture() in ['amd64', 'x86_64']: @@ -69,6 +75,7 @@ class RegisterCommandsTestCase(TestBase) self.build() self.convenience_registers_with_process_attach(test_16bit_regs=False) + @skipIfiOSSimulator def test_convenience_registers_16bit_with_process_attach(self): """Test convenience registers after a 'process attach'.""" if not self.getArchitecture() in ['amd64', 'x86_64']: Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py Wed Nov 4 18:46:25 2015 @@ -19,6 +19,7 @@ class CreateAfterAttachTestCase(TestBase # not yet investigated. Revisit once required functionality # is implemented for FreeBSD. @skipIfWindows # Occasionally hangs on Windows, may be same as other issues. + @skipIfiOSSimulator def test_create_after_attach_with_popen(self): """Test thread creation after process attach.""" self.build(dictionary=self.getBuildFlags(use_cpp11=False)) @@ -29,6 +30,7 @@ class CreateAfterAttachTestCase(TestBase @skipIfRemote @skipIfWindows # Windows doesn't have fork. @expectedFlakeyLinux("llvm.org/pr16229") # 1/100 dosep, build 3546, clang-3.5 x84_64 + @skipIfiOSSimulator def test_create_after_attach_with_fork(self): """Test thread creation after process attach.""" self.build(dictionary=self.getBuildFlags(use_cpp11=False)) Modified: lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py Wed Nov 4 18:46:25 2015 @@ -868,6 +868,10 @@ def skipIfNoSBHeaders(func): func(*args, **kwargs) return wrapper +def skipIfiOSSimulator(func): + """Decorate the item to skip tests that should be skipped on the iOS Simulator.""" + return unittest2.skipIf(hasattr(lldb, 'remote_platform_name') and lldb.remote_platform_name == 'ios-simulator', 'skip on the iOS Simulator')(func) + def skipIfFreeBSD(func): """Decorate the item to skip tests that should be skipped on FreeBSD.""" return skipIfPlatform(["freebsd"])(func) Modified: lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules (original) +++ lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules Wed Nov 4 18:46:25 2015 @@ -40,7 +40,7 @@ ifneq "$(TRIPLE)" "" triple_space = $(subst -, ,$(TRIPLE)) ARCH =$(word 1, $(triple_space)) TRIPLE_VENDOR =$(word 2, $(triple_space)) - triple_os_and_version =$(shell echo $(word 3, $(triple_space)) | sed -e 's/\(.*\)\([0-9]\.[0-9]\).*/\1 \2/') + triple_os_and_version =$(shell echo $(word 3, $(triple_space)) | sed 's/\([a-z]*\)\(.*\)/\1 \2/') TRIPLE_OS =$(word 1, $(triple_os_and_version)) TRIPLE_VERSION =$(word 2, $(triple_os_and_version)) ifeq "$(TRIPLE_VENDOR)" "apple" @@ -181,6 +181,7 @@ ifeq "$(OS)" "Darwin" else CFLAGS += $(ARCHFLAG)$(ARCH) $(FRAMEWORK_INCLUDES) $(CFLAGS_EXTRAS) -I$(LLDB_BASE_DIR)include endif + CFLAGS += -include $(THIS_FILE_DIR)test_common.h $(TRIPLE_CFLAGS) # Use this one if you want to build one part of the result without debug information: Modified: lldb/trunk/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py Wed Nov 4 18:46:25 2015 @@ -30,6 +30,7 @@ class HelloWorldTestCase(TestBase): TestBase.tearDown(self) @add_test_categories(['pyapi']) + @skipIfiOSSimulator def test_with_process_launch_api(self): """Create target, breakpoint, launch a process, and then kill it.""" self.build(dictionary=self.d) @@ -75,6 +76,7 @@ class HelloWorldTestCase(TestBase): @add_test_categories(['pyapi']) @expectedFailureWindows("llvm.org/pr24600") @expectedFailurei386("llvm.org/pr25338") + @skipIfiOSSimulator def test_with_attach_to_process_with_id_api(self): """Create target, spawn a process, and attach to it with process id.""" self.build(dictionary=self.d) @@ -104,6 +106,7 @@ class HelloWorldTestCase(TestBase): @add_test_categories(['pyapi']) @expectedFailureWindows("llvm.org/pr24600") @expectedFailurei386("llvm.org/pr25338") + @skipIfiOSSimulator def test_with_attach_to_process_with_name_api(self): """Create target, spawn a process, and attach to it with process name.""" self.build(dictionary=self.d) Modified: lldb/trunk/source/Plugins/Platform/MacOSX/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/CMakeLists.txt?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/CMakeLists.txt (original) +++ lldb/trunk/source/Plugins/Platform/MacOSX/CMakeLists.txt Wed Nov 4 18:46:25 2015 @@ -1,7 +1,9 @@ add_lldb_library(lldbPluginPlatformMacOSX + PlatformAppleSimulator.cpp PlatformDarwin.cpp PlatformDarwinKernel.cpp PlatformiOSSimulator.cpp + PlatformiOSSimulatorCoreSimulatorSupport.mm PlatformMacOSX.cpp PlatformRemoteiOS.cpp ) Added: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp?rev=252112&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp (added) +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp Wed Nov 4 18:46:25 2015 @@ -0,0 +1,300 @@ +//===-- PlatformAppleSimulator.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PlatformAppleSimulator.h" + +// C Includes +#include <dlfcn.h> +// C++ Includes +#include <mutex> +#include <thread> +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Error.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/PseudoTerminal.h" + +using namespace lldb; +using namespace lldb_private; + +#if !defined(__APPLE__) +#define UNSUPPORTED_ERROR ("Apple simulators aren't supported on this platform") +#endif + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ +void +PlatformAppleSimulator::Initialize () +{ + PlatformDarwin::Initialize (); +} + +void +PlatformAppleSimulator::Terminate () +{ + PlatformDarwin::Terminate (); +} + +//------------------------------------------------------------------ +/// Default Constructor +//------------------------------------------------------------------ +PlatformAppleSimulator::PlatformAppleSimulator () : + PlatformDarwin (true), + m_core_simulator_framework_path() +{ +} + +//------------------------------------------------------------------ +/// Destructor. +/// +/// The destructor is virtual since this class is designed to be +/// inherited from by the plug-in instance. +//------------------------------------------------------------------ +PlatformAppleSimulator::~PlatformAppleSimulator() +{ +} + +lldb_private::Error +PlatformAppleSimulator::LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info) +{ +#if defined(__APPLE__) + LoadCoreSimulator(); + CoreSimulatorSupport::Device device(GetSimulatorDevice()); + + if (device.GetState() != CoreSimulatorSupport::Device::State::Booted) + { + Error boot_err; + device.Boot(boot_err); + if (boot_err.Fail()) + return boot_err; + } + + auto spawned = device.Spawn(launch_info); + + if (spawned) + { + launch_info.SetProcessID(spawned.GetPID()); + return Error(); + } + else + return spawned.GetError(); +#else + Error err; + err.SetErrorString(UNSUPPORTED_ERROR); + return err; +#endif +} + +void +PlatformAppleSimulator::GetStatus (Stream &strm) +{ +#if defined(__APPLE__) + // This will get called by subclasses, so just output status on the + // current simulator + PlatformAppleSimulator::LoadCoreSimulator(); + + CoreSimulatorSupport::DeviceSet devices = CoreSimulatorSupport::DeviceSet::GetAvailableDevices(); + const size_t num_devices = devices.GetNumDevices(); + if (num_devices) + { + strm.Printf("Available devices:\n"); + for (size_t i=0; i<num_devices; ++i) + { + CoreSimulatorSupport::Device device = devices.GetDeviceAtIndex(i); + strm.Printf(" %s: %s\n", device.GetUDID().c_str(), device.GetName().c_str()); + } + + if (m_device.hasValue() && m_device->operator bool()) + { + strm.Printf("Current device: %s: %s", m_device->GetUDID().c_str(), m_device->GetName().c_str()); + if (m_device->GetState() == CoreSimulatorSupport::Device::State::Booted) + { + strm.Printf(" state = booted"); + } + strm.Printf("\nType \"platform connect <ARG>\" where <ARG> is a device UDID or a device name to disconnect and connect to a different device.\n"); + + } + else + { + strm.Printf("No current device is selected, \"platform connect <ARG>\" where <ARG> is a device UDID or a device name to connect to a specific device.\n"); + } + + } + else + { + strm.Printf("No devices are available.\n"); + } +#else + strm.Printf(UNSUPPORTED_ERROR); +#endif +} + +Error +PlatformAppleSimulator::ConnectRemote (Args& args) +{ +#if defined(__APPLE__) + Error error; + if (args.GetArgumentCount() == 1) + { + if (m_device) + DisconnectRemote (); + PlatformAppleSimulator::LoadCoreSimulator(); + const char *arg_cstr = args.GetArgumentAtIndex(0); + if (arg_cstr) + { + std::string arg_str(arg_cstr); + CoreSimulatorSupport::DeviceSet devices = CoreSimulatorSupport::DeviceSet::GetAvailableDevices(); + devices.ForEach([this, &arg_str](const CoreSimulatorSupport::Device &device) -> bool { + if (arg_str == device.GetUDID() || arg_str == device.GetName()) + { + m_device = device; + return false; // Stop iterating + } + else + { + return true; // Keep iterating + } + }); + if (!m_device) + error.SetErrorStringWithFormat("no device with UDID or name '%s' was found", arg_cstr); + } + } + else + { + error.SetErrorString("this command take a single UDID argument of the device you want to connect to."); + } + return error; +#else + Error err; + err.SetErrorString(UNSUPPORTED_ERROR); + return err; +#endif +} + +Error +PlatformAppleSimulator::DisconnectRemote () +{ +#if defined(__APPLE__) + m_device.reset(); + return Error(); +#else + Error err; + err.SetErrorString(UNSUPPORTED_ERROR); + return err; +#endif +} + + +lldb::ProcessSP +PlatformAppleSimulator::DebugProcess (ProcessLaunchInfo &launch_info, + Debugger &debugger, + Target *target, // Can be NULL, if NULL create a new target, else use existing one + Error &error) +{ +#if defined(__APPLE__) + ProcessSP process_sp; + // Make sure we stop at the entry point + launch_info.GetFlags ().Set (eLaunchFlagDebug); + // We always launch the process we are going to debug in a separate process + // group, since then we can handle ^C interrupts ourselves w/o having to worry + // about the target getting them as well. + launch_info.SetLaunchInSeparateProcessGroup(true); + + error = LaunchProcess (launch_info); + if (error.Success()) + { + if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) + { + ProcessAttachInfo attach_info (launch_info); + process_sp = Attach (attach_info, debugger, target, error); + if (process_sp) + { + launch_info.SetHijackListener(attach_info.GetHijackListener()); + + // Since we attached to the process, it will think it needs to detach + // if the process object just goes away without an explicit call to + // Process::Kill() or Process::Detach(), so let it know to kill the + // process if this happens. + process_sp->SetShouldDetach (false); + + // If we didn't have any file actions, the pseudo terminal might + // have been used where the slave side was given as the file to + // open for stdin/out/err after we have already opened the master + // so we can read/write stdin/out/err. + int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); + if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) + { + process_sp->SetSTDIOFileDescriptor(pty_fd); + } + } + } + } + + return process_sp; +#else + return ProcessSP(); +#endif +} + +FileSpec +PlatformAppleSimulator::GetCoreSimulatorPath() +{ +#if defined(__APPLE__) + Mutex::Locker locker (m_mutex); + if (!m_core_simulator_framework_path.hasValue()) + { + const char *developer_dir = GetDeveloperDirectory(); + if (developer_dir) + { + StreamString cs_path; + cs_path.Printf("%s/Library/PrivateFrameworks/CoreSimulator.framework/CoreSimulator", developer_dir); + const bool resolve_path = true; + m_core_simulator_framework_path = FileSpec(cs_path.GetData(), resolve_path); + } + } + + return m_core_simulator_framework_path.getValue(); +#else + return FileSpec(); +#endif +} + +void +PlatformAppleSimulator::LoadCoreSimulator () +{ +#if defined(__APPLE__) + static std::once_flag g_load_core_sim_flag; + std::call_once(g_load_core_sim_flag, [this] { + const std::string core_sim_path(GetCoreSimulatorPath().GetPath()); + if (core_sim_path.size()) + dlopen(core_sim_path.c_str(), RTLD_LAZY); + }); +#endif +} + +#if defined(__APPLE__) +CoreSimulatorSupport::Device +PlatformAppleSimulator::GetSimulatorDevice () +{ + if (!m_device.hasValue()) + { + const CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id = CoreSimulatorSupport::DeviceType::ProductFamilyID::iPhone; + m_device = CoreSimulatorSupport::DeviceSet::GetAvailableDevices().GetFanciest(dev_id); + } + + if (m_device.hasValue()) + return m_device.getValue(); + else + return CoreSimulatorSupport::Device(); +} +#endif + Added: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h?rev=252112&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h (added) +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h Wed Nov 4 18:46:25 2015 @@ -0,0 +1,81 @@ +//===-- PlatformAppleSimulator.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PlatformAppleSimulator_h_ +#define liblldb_PlatformAppleSimulator_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Host/FileSpec.h" +#include "PlatformDarwin.h" +#include "PlatformiOSSimulatorCoreSimulatorSupport.h" + +#include "llvm/ADT/Optional.h" + +class PlatformAppleSimulator : public PlatformDarwin +{ +public: + //------------------------------------------------------------ + // Class Functions + //------------------------------------------------------------ + static void + Initialize (); + + static void + Terminate (); + + //------------------------------------------------------------ + // Class Methods + //------------------------------------------------------------ + PlatformAppleSimulator (); + + virtual + ~PlatformAppleSimulator(); + + lldb_private::Error + LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info) override; + + void + GetStatus (lldb_private::Stream &strm) override; + + lldb_private::Error + ConnectRemote (lldb_private::Args& args) override; + + lldb_private::Error + DisconnectRemote () override; + + lldb::ProcessSP + DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Error &error) override; + +protected: + llvm::Optional<lldb_private::FileSpec> m_core_simulator_framework_path; + llvm::Optional<CoreSimulatorSupport::Device> m_device; + + lldb_private::FileSpec + GetCoreSimulatorPath(); + + void + LoadCoreSimulator (); + +#if defined(__APPLE__) + CoreSimulatorSupport::Device + GetSimulatorDevice (); +#endif + +private: + DISALLOW_COPY_AND_ASSIGN (PlatformAppleSimulator); + +}; + +#endif // liblldb_PlatformAppleSimulator_h_ Modified: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp (original) +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp Wed Nov 4 18:46:25 2015 @@ -41,8 +41,8 @@ static uint32_t g_initialize_count = 0; void PlatformiOSSimulator::Initialize () { - PlatformDarwin::Initialize (); - + PlatformAppleSimulator::Initialize (); + if (g_initialize_count++ == 0) { PluginManager::RegisterPlugin (PlatformiOSSimulator::GetPluginNameStatic(), @@ -61,8 +61,8 @@ PlatformiOSSimulator::Terminate () PluginManager::UnregisterPlugin (PlatformiOSSimulator::CreateInstance); } } - - PlatformDarwin::Terminate (); + + PlatformAppleSimulator::Terminate (); } PlatformSP @@ -73,8 +73,8 @@ PlatformiOSSimulator::CreateInstance (bo { switch (arch->GetMachine()) { - case llvm::Triple::x86_64: - case llvm::Triple::x86: + case llvm::Triple::x86_64: + case llvm::Triple::x86: { const llvm::Triple &triple = arch->GetTriple(); switch (triple.getVendor()) @@ -84,9 +84,9 @@ PlatformiOSSimulator::CreateInstance (bo break; #if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the vendor if the host is Apple and + // it "unknown" wasn't specified (it was just returned because it + // was NOT specified) case llvm::Triple::UnknownArch: create = !arch->TripleVendorWasSpecified(); break; @@ -105,9 +105,9 @@ PlatformiOSSimulator::CreateInstance (bo break; #if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the OS if the host is Apple and + // it "unknown" wasn't specified (it was just returned because it + // was NOT specified) case llvm::Triple::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -118,9 +118,9 @@ PlatformiOSSimulator::CreateInstance (bo } } } - break; - default: - break; + break; + default: + break; } } if (create) @@ -147,8 +147,8 @@ PlatformiOSSimulator::GetDescriptionStat /// Default Constructor //------------------------------------------------------------------ PlatformiOSSimulator::PlatformiOSSimulator () : - PlatformDarwin (true), - m_sdk_directory () +PlatformAppleSimulator (), +m_sdk_directory () { } @@ -167,11 +167,12 @@ void PlatformiOSSimulator::GetStatus (Stream &strm) { Platform::GetStatus (strm); - const char *sdk_directory = GetSDKsDirectory(); + const char *sdk_directory = GetSDKDirectoryAsCString(); if (sdk_directory) strm.Printf (" SDK Path: \"%s\"\n", sdk_directory); else strm.PutCString (" SDK Path: error: unable to locate SDK\n"); + PlatformAppleSimulator::GetStatus(strm); } @@ -182,29 +183,29 @@ PlatformiOSSimulator::ResolveExecutable { Error error; // Nothing special to do here, just use the actual file and architecture - + ModuleSpec resolved_module_spec(module_spec); - + // If we have "ls" as the exe_file, resolve the executable loation based on // the current path variables // TODO: resolve bare executables in the Platform SDK -// if (!resolved_exe_file.Exists()) -// resolved_exe_file.ResolveExecutableLocation (); - + // if (!resolved_exe_file.Exists()) + // resolved_exe_file.ResolveExecutableLocation (); + // Resolve any executable within a bundle on MacOSX // TODO: verify that this handles shallow bundles, if not then implement one ourselves Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); - + if (resolved_module_spec.GetFileSpec().Exists()) { if (resolved_module_spec.GetArchitecture().IsValid()) { error = ModuleList::GetSharedModule (resolved_module_spec, - exe_module_sp, + exe_module_sp, + NULL, NULL, - NULL, NULL); - + if (exe_module_sp && exe_module_sp->GetObjectFile()) return error; exe_module_sp.reset(); @@ -220,11 +221,11 @@ PlatformiOSSimulator::ResolveExecutable if (!module_spec.GetArchitecture().IsValid() || module_spec.GetArchitecture().GetCore() == resolved_module_spec.GetArchitecture().GetCore()) { error = ModuleList::GetSharedModule (resolved_module_spec, - exe_module_sp, + exe_module_sp, + NULL, NULL, - NULL, NULL); - // Did we find an executable using one of the + // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) @@ -259,11 +260,11 @@ PlatformiOSSimulator::ResolveExecutable error.SetErrorStringWithFormat ("'%s' does not exist", module_spec.GetFileSpec().GetPath().c_str()); } - + return error; } -static FileSpec::EnumerateDirectoryResult +static FileSpec::EnumerateDirectoryResult EnumerateDirectoryCallback (void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) { if (file_type == FileSpec::eFileTypeDirectory) @@ -281,8 +282,9 @@ EnumerateDirectoryCallback (void *baton, const char * -PlatformiOSSimulator::GetSDKsDirectory() +PlatformiOSSimulator::GetSDKDirectoryAsCString() { + Mutex::Locker locker (m_mutex); if (m_sdk_directory.empty()) { const char *developer_dir = GetDeveloperDirectory(); @@ -291,8 +293,8 @@ PlatformiOSSimulator::GetSDKsDirectory() char sdks_directory[PATH_MAX]; char sdk_dirname[PATH_MAX]; sdk_dirname[0] = '\0'; - snprintf (sdks_directory, - sizeof(sdks_directory), + snprintf (sdks_directory, + sizeof(sdks_directory), "%s/Platforms/iPhoneSimulator.platform/Developer/SDKs", developer_dir); FileSpec simulator_sdk_spec; @@ -318,7 +320,7 @@ PlatformiOSSimulator::GetSDKsDirectory() // support directory and we don't keep trying to find it over and over. m_sdk_directory.assign (1, '\0'); } - + // We should have put a single NULL character into m_sdk_directory // or it should have a valid path if the code gets here assert (m_sdk_directory.empty() == false); @@ -328,7 +330,7 @@ PlatformiOSSimulator::GetSDKsDirectory() } Error -PlatformiOSSimulator::GetSymbolFile (const FileSpec &platform_file, +PlatformiOSSimulator::GetSymbolFile (const FileSpec &platform_file, const UUID *uuid_ptr, FileSpec &local_file) { @@ -337,28 +339,28 @@ PlatformiOSSimulator::GetSymbolFile (con if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { char resolved_path[PATH_MAX]; - - const char * sdk_dir = GetSDKsDirectory(); + + const char * sdk_dir = GetSDKDirectoryAsCString(); if (sdk_dir) { - ::snprintf (resolved_path, - sizeof(resolved_path), - "%s/%s", - sdk_dir, + ::snprintf (resolved_path, + sizeof(resolved_path), + "%s/%s", + sdk_dir, platform_file_path); // First try in the SDK and see if the file is in there local_file.SetFile(resolved_path, true); if (local_file.Exists()) return error; - + // Else fall back to the actual path itself local_file.SetFile(platform_file_path, true); if (local_file.Exists()) return error; - + } - error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", + error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", platform_file_path, GetPluginName().GetCString()); } @@ -392,17 +394,17 @@ PlatformiOSSimulator::GetSharedModule (c else { const bool always_create = false; - error = ModuleList::GetSharedModule (module_spec, + error = ModuleList::GetSharedModule (module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, always_create); - + } if (module_sp) module_sp->SetPlatformFileSpec(platform_file); - + return error; } @@ -414,7 +416,7 @@ PlatformiOSSimulator::FindProcesses (con ProcessInstanceInfoList all_osx_process_infos; // First we get all OSX processes const uint32_t n = Host::FindProcesses (match_info, all_osx_process_infos); - + // Now we filter them down to only the iOS triples for (uint32_t i=0; i<n; ++i) { @@ -431,7 +433,7 @@ PlatformiOSSimulator::GetSupportedArchit { static const ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault)); static const ArchSpec platform_arch64(HostInfo::GetArchitecture(HostInfo::eArchKind64)); - + if (idx == 0) { arch = platform_arch; Modified: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h?rev=252112&r1=252111&r2=252112&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h (original) +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h Wed Nov 4 18:46:25 2015 @@ -16,30 +16,30 @@ // Other libraries and framework includes // Project includes -#include "PlatformDarwin.h" +#include "PlatformAppleSimulator.h" -class PlatformiOSSimulator : public PlatformDarwin +class PlatformiOSSimulator : public PlatformAppleSimulator { public: PlatformiOSSimulator (); - + ~PlatformiOSSimulator() override; - + //------------------------------------------------------------ // Class Functions //------------------------------------------------------------ static lldb::PlatformSP CreateInstance (bool force, const lldb_private::ArchSpec *arch); - + static void Initialize (); - + static void Terminate (); static lldb_private::ConstString GetPluginNameStatic (); - + static const char * GetDescriptionStatic(); @@ -57,7 +57,7 @@ public: { return 1; } - + //------------------------------------------------------------ // lldb_private::Platform functions //------------------------------------------------------------ @@ -65,21 +65,21 @@ public: ResolveExecutable (const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr) override; - + const char * GetDescription () override { return GetDescriptionStatic(); } - + void GetStatus (lldb_private::Stream &strm) override; - + virtual lldb_private::Error - GetSymbolFile (const lldb_private::FileSpec &platform_file, + GetSymbolFile (const lldb_private::FileSpec &platform_file, const lldb_private::UUID *uuid_ptr, lldb_private::FileSpec &local_file); - + lldb_private::Error GetSharedModule (const lldb_private::ModuleSpec &module_spec, lldb_private::Process* process, @@ -87,13 +87,13 @@ public: const lldb_private::FileSpecList *module_search_paths_ptr, lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr) override; - + uint32_t FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info, lldb_private::ProcessInstanceInfoList &process_infos) override; - + bool - GetSupportedArchitectureAtIndex (uint32_t idx, + GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch) override; void @@ -101,15 +101,14 @@ public: { return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(target, options, PlatformDarwin::SDKType::iPhoneSimulator); } - + protected: std::string m_sdk_directory; std::string m_build_update; - //std::vector<FileSpec> m_device_support_os_dirs; const char * - GetSDKsDirectory(); - + GetSDKDirectoryAsCString(); + private: DISALLOW_COPY_AND_ASSIGN (PlatformiOSSimulator); }; Added: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h?rev=252112&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h (added) +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h Wed Nov 4 18:46:25 2015 @@ -0,0 +1,315 @@ +//===-- PlatformiOSSimulatorCoreSimulatorSupport.h ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_ +#define liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_ + +// C Includes +// C++ Includes +#include <functional> +#include <string> +#include <ostream> +#include <vector> +// Other libraries and framework includes +#ifdef __APPLE__ +#include <objc/objc.h> +#else +typedef void *id; +#endif +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Target/ProcessLaunchInfo.h" + +#include "llvm/ADT/Optional.h" + +// And now the actual magic +namespace CoreSimulatorSupport +{ + class Process + { + public: + pid_t + GetPID () + { + return m_pid; + } + + explicit operator bool () + { + return m_pid != LLDB_INVALID_PROCESS_ID; + } + + lldb_private::Error + GetError () + { + return m_error; + } + + private: + Process (pid_t p); + + Process(lldb_private::Error error); + + Process (pid_t p, lldb_private::Error error); + + pid_t m_pid; + lldb_private::Error m_error; + + friend class Device; + }; + + class ModelIdentifier { + public: + ModelIdentifier (const std::string& mi); + ModelIdentifier (); + + explicit operator bool () const + { + return !m_versions.empty(); + } + + size_t + GetNumVersions () const + { + return m_versions.size(); + } + + unsigned int + GetVersionAtIndex (size_t idx) const + { + return m_versions[idx]; + } + + std::string + GetFamily () const + { + return m_family.c_str(); + } + + private: + std::string m_family; + std::vector<unsigned int> m_versions; + }; + + class DeviceType + { + public: + enum class ProductFamilyID : int32_t + { + iPhone = 1, + iPad = 2, + appleTV = 3, + appleWatch = 4 + }; + + DeviceType (); + + DeviceType (id d); + + explicit operator bool (); + + std::string + GetName (); + + lldb_private::ConstString + GetIdentifier (); + + ModelIdentifier + GetModelIdentifier (); + + lldb_private::ConstString + GetProductFamily (); + + ProductFamilyID + GetProductFamilyID (); + + private: + id m_dev; + llvm::Optional<ModelIdentifier> m_model_identifier; + }; + + class OSVersion { + public: + OSVersion (const std::string& ver, + const std::string& build); + + OSVersion (); + + explicit operator bool () const + { + return !m_versions.empty(); + } + + size_t + GetNumVersions () const + { + return m_versions.size(); + } + + unsigned int + GetVersionAtIndex (size_t idx) const + { + return m_versions[idx]; + } + + const char* + GetBuild () const + { + return m_build.c_str(); + } + + private: + std::vector<unsigned int> m_versions; + std::string m_build; + }; + + class DeviceRuntime + { + public: + DeviceRuntime (); + + DeviceRuntime (id d); + + explicit operator bool (); + + OSVersion + GetVersion (); + + bool + IsAvailable (); + + private: + id m_dev; + llvm::Optional<OSVersion> m_os_version; + }; + + class Device + { + private: + typedef unsigned long int NSUInteger; + + public: + enum class State : NSUInteger + { + Creating, + Shutdown, + Booting, + Booted, + ShuttingDown + }; + + Device (); + + Device (id d); + + explicit operator bool (); + + std::string + GetName () const; + + DeviceType + GetDeviceType (); + + DeviceRuntime + GetDeviceRuntime (); + + State + GetState (); + + bool + Boot (lldb_private::Error &err); + + bool + Shutdown (lldb_private::Error &err); + + std::string + GetUDID () const; + + Process + Spawn (lldb_private::ProcessLaunchInfo& launch_info); + + private: + id m_dev; + llvm::Optional<DeviceType> m_dev_type; + llvm::Optional<DeviceRuntime> m_dev_runtime; + + friend class DeviceSet; + }; + + bool + operator > (const OSVersion& lhs, + const OSVersion& rhs); + + bool + operator > (const ModelIdentifier& lhs, + const ModelIdentifier& rhs); + + bool + operator < (const OSVersion& lhs, + const OSVersion& rhs); + + bool + operator < (const ModelIdentifier& lhs, + const ModelIdentifier& rhs); + + bool + operator == (const OSVersion& lhs, + const OSVersion& rhs); + + bool + operator == (const ModelIdentifier& lhs, + const ModelIdentifier& rhs); + + bool + operator != (const OSVersion& lhs, + const OSVersion& rhs); + + bool + operator != (const ModelIdentifier& lhs, + const ModelIdentifier& rhs); + + class DeviceSet + { + public: + static DeviceSet + GetAllDevices (); + + static DeviceSet + GetAvailableDevices (); + + size_t + GetNumDevices (); + + Device + GetDeviceAtIndex (size_t idx); + + void + ForEach (std::function<bool(const Device &)> f); + + DeviceSet + GetDevicesIf (std::function<bool(Device)> f); + + DeviceSet + GetDevices (DeviceType::ProductFamilyID dev_id); + + Device + GetFanciest (DeviceType::ProductFamilyID dev_id); + + private: + DeviceSet (id arr) : m_dev(arr) + { + } + + id m_dev; + }; +} + +#endif // liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_ Added: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm?rev=252112&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm (added) +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm Wed Nov 4 18:46:25 2015 @@ -0,0 +1,773 @@ +//===-- PlatformiOSSimulatorCoreSimulatorSupport.cpp ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PlatformiOSSimulatorCoreSimulatorSupport.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include <CoreFoundation/CoreFoundation.h> +#include <Foundation/Foundation.h> +// Project includes +#include "lldb/Target/FileAction.h" +#include "lldb/Utility/PseudoTerminal.h" + +#include "llvm/ADT/StringRef.h" + +using namespace lldb_private; +using namespace lldb_utility; +// CoreSimulator lives as part of Xcode, which means we can't really link against it, so we dlopen() +// it at runtime, and error out nicely if that fails +@interface SimDeviceSet +{} ++ (id) defaultSet; +@end +// However, the drawback is that the compiler will not know about the selectors we're trying to use +// until runtime; to appease clang in this regard, define a fake protocol on NSObject that exposes +// the needed interface names for us +@protocol LLDBCoreSimulatorSupport <NSObject> +- (NSArray *) devices; +- (id) deviceType; +- (NSString *) name; +- (NSString *) identifier; +- (NSString *) modelIdentifier; +- (NSString *) productFamily; +- (int32_t) productFamilyID; +- (id) runtime; +- (BOOL) available; +- (NSString *) versionString; +- (NSString *) buildVersionString; +- (BOOL) bootWithOptions:(NSDictionary *)options error:(NSError**)error; +- (NSUInteger) state; +- (BOOL) shutdownWithError:(NSError **)error; +- (NSUUID *) UDID; +- (pid_t) spawnWithPath:(NSString *)path options:(NSDictionary *)options terminationHandler:(void (^)(int status)) terminationHandler error:(NSError **)error; +@end + +CoreSimulatorSupport::Process::Process (pid_t p) : + m_pid (p), + m_error () +{ +} + +CoreSimulatorSupport::Process::Process(Error error) : + m_pid (LLDB_INVALID_PROCESS_ID), + m_error (error) +{ +} + +CoreSimulatorSupport::Process::Process (pid_t p, Error error) : + m_pid (p), + m_error (error) +{ +} + + +CoreSimulatorSupport::DeviceType::DeviceType () : + m_dev (nil), + m_model_identifier () +{ +} + +CoreSimulatorSupport::DeviceType::DeviceType (id d) : + m_dev (d), + m_model_identifier () +{ +} + +CoreSimulatorSupport::DeviceType::operator bool () +{ + return m_dev != nil; +} + +ConstString +CoreSimulatorSupport::DeviceType::GetIdentifier () +{ + return ConstString( [[m_dev identifier] UTF8String] ); +} + +ConstString +CoreSimulatorSupport::DeviceType::GetProductFamily () +{ + return ConstString( [[m_dev productFamily] UTF8String] ); +} + +CoreSimulatorSupport::DeviceType::ProductFamilyID +CoreSimulatorSupport::DeviceType::GetProductFamilyID () +{ + return ProductFamilyID([m_dev productFamilyID]); +} + +CoreSimulatorSupport::DeviceRuntime::DeviceRuntime () : + m_dev (nil), + m_os_version () +{ +} + +CoreSimulatorSupport::DeviceRuntime::DeviceRuntime (id d) : + m_dev (d), + m_os_version () +{ +} + +CoreSimulatorSupport::DeviceRuntime::operator bool () +{ + return m_dev != nil; +} + +bool +CoreSimulatorSupport::DeviceRuntime::IsAvailable () +{ + return [m_dev available]; +} + +CoreSimulatorSupport::Device::Device () : + m_dev (nil), + m_dev_type (), + m_dev_runtime () +{ +} + +CoreSimulatorSupport::Device::Device (id d) : + m_dev (d), + m_dev_type (), + m_dev_runtime () +{ +} + +CoreSimulatorSupport::Device::operator bool () +{ + return m_dev != nil; +} + +CoreSimulatorSupport::Device::State +CoreSimulatorSupport::Device::GetState () +{ + return (State)([m_dev state]); +} + +CoreSimulatorSupport::ModelIdentifier::ModelIdentifier (const std::string& mi) : + m_family (), + m_versions () +{ + bool any = false; + bool first_digit = false; + unsigned int val = 0; + + for (char c : mi) + { + any = true; + if (::isdigit(c)) + { + if (!first_digit) + first_digit = true; + val = 10*val + (c - '0'); + } + else if (c == ',') + { + if (first_digit) + { + m_versions.push_back(val); + val = 0; + } + else + m_family.push_back(c); + } + else + { + if (first_digit) + { + m_family.clear(); + m_versions.clear(); + return; + } + else + { + m_family.push_back(c); + } + } + } + + if (first_digit) + m_versions.push_back(val); +} + +CoreSimulatorSupport::ModelIdentifier::ModelIdentifier () : +ModelIdentifier("") +{ +} + +CoreSimulatorSupport::OSVersion::OSVersion (const std::string& ver, + const std::string& build) : + m_versions (), + m_build (build) +{ + bool any = false; + unsigned int val = 0; + for (char c : ver) + { + if (c == '.') + { + m_versions.push_back(val); + val = 0; + } + else if (::isdigit(c)) + { + val = 10*val + (c - '0'); + any = true; + } + else + { + m_versions.clear(); + return; + } + } + if (any) + m_versions.push_back(val); +} + +CoreSimulatorSupport::OSVersion::OSVersion () : + OSVersion("","") +{ +} + +CoreSimulatorSupport::ModelIdentifier +CoreSimulatorSupport::DeviceType::GetModelIdentifier () +{ + if (!m_model_identifier.hasValue()) + { + auto utf8_model_id = [[m_dev modelIdentifier] UTF8String]; + if (utf8_model_id && *utf8_model_id) + m_model_identifier = ModelIdentifier (utf8_model_id); + } + + if (m_model_identifier.hasValue()) + return m_model_identifier.getValue(); + else + return ModelIdentifier(); +} + +CoreSimulatorSupport::OSVersion +CoreSimulatorSupport::DeviceRuntime::GetVersion () +{ + if (!m_os_version.hasValue()) + { + auto utf8_ver_string = [[m_dev versionString] UTF8String]; + auto utf8_build_ver = [[m_dev buildVersionString] UTF8String]; + if (utf8_ver_string && *utf8_ver_string && + utf8_build_ver && *utf8_build_ver) + { + m_os_version = OSVersion(utf8_ver_string, utf8_build_ver); + } + } + + if (m_os_version.hasValue()) + return m_os_version.getValue(); + return OSVersion(); +} + +std::string +CoreSimulatorSupport::DeviceType::GetName () +{ + auto utf8_name = [[m_dev name] UTF8String]; + if (utf8_name) + return std::string(utf8_name); + return ""; +} + +std::string +CoreSimulatorSupport::Device::GetName () const +{ + auto utf8_name = [[m_dev name] UTF8String]; + if (utf8_name) + return std::string(utf8_name); + return ""; +} + +std::string +CoreSimulatorSupport::Device::GetUDID () const +{ + auto utf8_udid = [ [[m_dev UDID] UUIDString] UTF8String]; + if (utf8_udid) + return std::string(utf8_udid); + else + return std::string(); +} + +CoreSimulatorSupport::DeviceType +CoreSimulatorSupport::Device::GetDeviceType () +{ + if (!m_dev_type.hasValue()) + m_dev_type = DeviceType([m_dev deviceType]); + + return m_dev_type.getValue(); +} + +CoreSimulatorSupport::DeviceRuntime +CoreSimulatorSupport::Device::GetDeviceRuntime () +{ + if (!m_dev_runtime.hasValue()) + m_dev_runtime = DeviceRuntime([m_dev runtime]); + + return m_dev_runtime.getValue(); +} + +bool +CoreSimulatorSupport::operator > (const CoreSimulatorSupport::OSVersion& lhs, + const CoreSimulatorSupport::OSVersion& rhs) +{ + for (size_t i = 0; + i < rhs.GetNumVersions(); + i++) + { + unsigned int l = lhs.GetVersionAtIndex(i); + unsigned int r = rhs.GetVersionAtIndex(i); + if (l > r) + return true; + } + return false; +} + +bool +CoreSimulatorSupport::operator > (const CoreSimulatorSupport::ModelIdentifier& lhs, + const CoreSimulatorSupport::ModelIdentifier& rhs) +{ + if (lhs.GetFamily() != rhs.GetFamily()) + return false; + for (size_t i = 0; + i < rhs.GetNumVersions(); + i++) + { + unsigned int l = lhs.GetVersionAtIndex(i); + unsigned int r = rhs.GetVersionAtIndex(i); + if (l > r) + return true; + } + return false; +} + +bool +CoreSimulatorSupport::operator < (const CoreSimulatorSupport::OSVersion& lhs, + const CoreSimulatorSupport::OSVersion& rhs) +{ + for (size_t i = 0; + i < rhs.GetNumVersions(); + i++) + { + unsigned int l = lhs.GetVersionAtIndex(i); + unsigned int r = rhs.GetVersionAtIndex(i); + if (l < r) + return true; + } + return false; +} + +bool +CoreSimulatorSupport::operator < (const CoreSimulatorSupport::ModelIdentifier& lhs, + const CoreSimulatorSupport::ModelIdentifier& rhs) +{ + if (lhs.GetFamily() != rhs.GetFamily()) + return false; + + for (size_t i = 0; + i < rhs.GetNumVersions(); + i++) + { + unsigned int l = lhs.GetVersionAtIndex(i); + unsigned int r = rhs.GetVersionAtIndex(i); + if (l < r) + return true; + } + return false; +} + +bool +CoreSimulatorSupport::operator == (const CoreSimulatorSupport::OSVersion& lhs, + const CoreSimulatorSupport::OSVersion& rhs) +{ + for (size_t i = 0; + i < rhs.GetNumVersions(); + i++) + { + unsigned int l = lhs.GetVersionAtIndex(i); + unsigned int r = rhs.GetVersionAtIndex(i); + if (l != r) + return false; + } + return true; +} + +bool +CoreSimulatorSupport::operator == (const CoreSimulatorSupport::ModelIdentifier& lhs, + const CoreSimulatorSupport::ModelIdentifier& rhs) +{ + if (lhs.GetFamily() != rhs.GetFamily()) + return false; + + for (size_t i = 0; + i < rhs.GetNumVersions(); + i++) + { + unsigned int l = lhs.GetVersionAtIndex(i); + unsigned int r = rhs.GetVersionAtIndex(i); + if (l != r) + return false; + } + return true; +} + +bool +CoreSimulatorSupport::operator != (const CoreSimulatorSupport::OSVersion& lhs, + const CoreSimulatorSupport::OSVersion& rhs) +{ + for (size_t i = 0; + i < rhs.GetNumVersions(); + i++) + { + unsigned int l = lhs.GetVersionAtIndex(i); + unsigned int r = rhs.GetVersionAtIndex(i); + if (l != r) + return true; + } + return false; +} + +bool +CoreSimulatorSupport::operator != (const CoreSimulatorSupport::ModelIdentifier& lhs, + const CoreSimulatorSupport::ModelIdentifier& rhs) +{ + if (lhs.GetFamily() != rhs.GetFamily()) + return false; + + for (size_t i = 0; + i < rhs.GetNumVersions(); + i++) + { + unsigned int l = lhs.GetVersionAtIndex(i); + unsigned int r = rhs.GetVersionAtIndex(i); + if (l != r) + return true; + } + return false; +} + +bool +CoreSimulatorSupport::Device::Boot (Error &err) +{ + if (m_dev == nil) + { + err.SetErrorString("no valid simulator instance"); + return false; + } + +#define kSimDeviceBootEnv @"env" /* An NSDictionary of "extra" environment key/values */ +#define kSimDeviceBootPersist @"persist" /* An NSNumber (boolean) indicating whether or not the session should outlive the calling process (default false) */ +#define kSimDeviceBootDisabledJobs @"disabled_jobs" /* An NSDictionary of NSStrings -> NSNumbers, each string is the name of a job, and the value is the corresponding state (true if disabled) */ + + NSDictionary *options = @{ + kSimDeviceBootPersist : @NO, + kSimDeviceBootDisabledJobs : @{@"com.apple.backboardd" : @YES} + }; + +#undef kSimDeviceBootEnv +#undef kSimDeviceBootPersist +#undef kSimDeviceBootDisabledJobs + + NSError* nserror; + if ([m_dev bootWithOptions:options error:&nserror]) + { + err.Clear(); + return true; + } + else + { + err.SetErrorString([[nserror description] UTF8String]); + return false; + } +} + +bool +CoreSimulatorSupport::Device::Shutdown (Error &err) +{ + NSError* nserror; + if ([m_dev shutdownWithError:&nserror]) + { + err.Clear(); + return true; + } + else + { + err.SetErrorString([[nserror description] UTF8String]); + return false; + } +} + + +static Error +HandleFileAction(ProcessLaunchInfo& launch_info, + NSMutableDictionary *options, + NSString *key, + const int fd, + File &file) +{ + Error error; + const FileAction *file_action = launch_info.GetFileActionForFD (fd); + if (file_action) + { + switch (file_action->GetAction()) + { + case FileAction::eFileActionNone: + break; + + case FileAction::eFileActionClose: + error.SetErrorStringWithFormat ("close file action for %i not supported", fd); + break; + + case FileAction::eFileActionDuplicate: + error.SetErrorStringWithFormat ("duplication file action for %i not supported", fd); + break; + + case FileAction::eFileActionOpen: + { + FileSpec file_spec = file_action->GetFileSpec(); + if (file_spec) + { + const int master_fd = launch_info.GetPTY().GetMasterFileDescriptor(); + if (master_fd != PseudoTerminal::invalid_fd) + { + // Check in case our file action open wants to open the slave + const char *slave_path = launch_info.GetPTY().GetSlaveName(NULL, 0); + if (slave_path) + { + FileSpec slave_spec(slave_path, false); + if (file_spec == slave_spec) + { + int slave_fd = launch_info.GetPTY().GetSlaveFileDescriptor(); + if (slave_fd == PseudoTerminal::invalid_fd) + slave_fd = launch_info.GetPTY().OpenSlave(O_RDWR, nullptr, 0); + if (slave_fd == PseudoTerminal::invalid_fd) + { + error.SetErrorStringWithFormat("unable to open slave pty '%s'", slave_path); + return error; // Failure + } + [options setValue:[NSNumber numberWithInteger:slave_fd] forKey:key]; + return error; // Success + } + } + } + Error posix_error; + int created_fd = open(file_spec.GetPath().c_str(), file_action->GetActionArgument(), S_IRUSR | S_IWUSR); + if (created_fd >= 0) + { + file.SetDescriptor(created_fd, true); + [options setValue:[NSNumber numberWithInteger:created_fd] forKey:key]; + return error; // Success + } + else + { + posix_error.SetErrorToErrno(); + error.SetErrorStringWithFormat("unable to open file '%s': %s", file_spec.GetPath().c_str(), posix_error.AsCString()); + } + } + } + break; + } + } + return error; // Success, no file action, nothing to do +} + +CoreSimulatorSupport::Process +CoreSimulatorSupport::Device::Spawn (ProcessLaunchInfo& launch_info) +{ +#define kSimDeviceSpawnEnvironment @"environment" /* An NSDictionary (NSStrings -> NSStrings) of environment key/values */ +#define kSimDeviceSpawnStdin @"stdin" /* An NSNumber corresponding to a fd */ +#define kSimDeviceSpawnStdout @"stdout" /* An NSNumber corresponding to a fd */ +#define kSimDeviceSpawnStderr @"stderr" /* An NSNumber corresponding to a fd */ +#define kSimDeviceSpawnArguments @"arguments" /* An NSArray of strings to use as the argv array. If not provided, path will be argv[0] */ +#define kSimDeviceSpawnWaitForDebugger @"wait_for_debugger" /* An NSNumber (bool) */ + + NSMutableDictionary *options = [[NSMutableDictionary alloc] init]; + + if (launch_info.GetFlags().Test(lldb::eLaunchFlagDebug)) + [options setObject:@YES forKey:kSimDeviceSpawnWaitForDebugger]; + + if (launch_info.GetArguments().GetArgumentCount()) + { + const Args& args(launch_info.GetArguments()); + NSMutableArray *args_array = [[NSMutableArray alloc] init]; + for (size_t idx = 0; + idx < args.GetArgumentCount(); + idx++) + [args_array addObject:[NSString stringWithUTF8String:args.GetArgumentAtIndex(idx)]]; + + [options setObject:args_array forKey:kSimDeviceSpawnArguments]; + } + + if (launch_info.GetEnvironmentEntries().GetArgumentCount()) + { + const Args& envs(launch_info.GetEnvironmentEntries()); + NSMutableDictionary *env_dict = [[NSMutableDictionary alloc] init]; + for (size_t idx = 0; + idx < envs.GetArgumentCount(); + idx++) + { + llvm::StringRef arg_sr(envs.GetArgumentAtIndex(idx)); + auto first_eq = arg_sr.find('='); + if (first_eq == llvm::StringRef::npos) + continue; + llvm::StringRef key = arg_sr.substr(0, first_eq); + llvm::StringRef value = arg_sr.substr(first_eq+1); + + NSString *key_ns = [NSString stringWithUTF8String:key.str().c_str()]; + NSString *value_ns = [NSString stringWithUTF8String:value.str().c_str()]; + + [env_dict setValue:value_ns forKey:key_ns]; + } + + [options setObject:env_dict forKey:kSimDeviceSpawnEnvironment]; + } + + Error error; + File stdin_file; + File stdout_file; + File stderr_file; + error = HandleFileAction(launch_info, options, kSimDeviceSpawnStdin, STDIN_FILENO, stdin_file); + + if (error.Fail()) + return CoreSimulatorSupport::Process(error); + + error = HandleFileAction(launch_info, options, kSimDeviceSpawnStdout, STDOUT_FILENO, stdout_file); + + if (error.Fail()) + return CoreSimulatorSupport::Process(error); + + error = HandleFileAction(launch_info, options, kSimDeviceSpawnStderr, STDERR_FILENO, stderr_file); + + if (error.Fail()) + return CoreSimulatorSupport::Process(error); + +#undef kSimDeviceSpawnEnvironment +#undef kSimDeviceSpawnStdin +#undef kSimDeviceSpawnStdout +#undef kSimDeviceSpawnStderr +#undef kSimDeviceSpawnWaitForDebugger +#undef kSimDeviceSpawnArguments + + NSError* nserror; + + pid_t pid = [m_dev spawnWithPath: [NSString stringWithUTF8String: launch_info.GetExecutableFile().GetPath().c_str()] + options: options + terminationHandler: nil + error: &nserror]; + + + if (pid < 0) + { + const char* nserror_string = [[nserror description] UTF8String]; + error.SetErrorString(nserror_string ? nserror_string : "unable to launch"); + } + + return CoreSimulatorSupport::Process (pid, error); +} + +CoreSimulatorSupport::DeviceSet +CoreSimulatorSupport::DeviceSet::GetAllDevices () +{ + return DeviceSet([[NSClassFromString(@"SimDeviceSet") defaultSet] devices]); +} + +CoreSimulatorSupport::DeviceSet +CoreSimulatorSupport::DeviceSet::GetAvailableDevices () +{ + return GetAllDevices().GetDevicesIf( [] (Device d) -> bool { + return (d && d.GetDeviceType() && d.GetDeviceRuntime() && d.GetDeviceRuntime().IsAvailable()); + }); +} + +size_t +CoreSimulatorSupport::DeviceSet::GetNumDevices () +{ + return [m_dev count]; +} + +CoreSimulatorSupport::Device +CoreSimulatorSupport::DeviceSet::GetDeviceAtIndex (size_t idx) +{ + if (idx < GetNumDevices()) + return Device([m_dev objectAtIndex:idx]); + return Device(); +} + +CoreSimulatorSupport::DeviceSet +CoreSimulatorSupport::DeviceSet::GetDevicesIf (std::function<bool(CoreSimulatorSupport::Device)> f) +{ + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (NSUInteger i = 0; + i < GetNumDevices(); + i++) + { + Device d(GetDeviceAtIndex(i)); + if (f(d)) + [array addObject:(id)d.m_dev]; + } + + return DeviceSet(array); +} + +void +CoreSimulatorSupport::DeviceSet::ForEach (std::function<bool(const Device &)> f) +{ + const size_t n = GetNumDevices(); + for (NSUInteger i = 0; i < n; ++i) + { + if (f(GetDeviceAtIndex(i)) == false) + break; + } +} + +CoreSimulatorSupport::DeviceSet +CoreSimulatorSupport::DeviceSet::GetDevices (CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id) +{ + NSMutableArray *array = [[NSMutableArray alloc] init]; + const size_t n = GetNumDevices(); + for (NSUInteger i = 0; i < n; ++i) + { + Device d(GetDeviceAtIndex(i)); + if (d && d.GetDeviceType() && d.GetDeviceType().GetProductFamilyID() == dev_id) + [array addObject:(id)d.m_dev]; + } + + return DeviceSet(array); +} + +CoreSimulatorSupport::Device +CoreSimulatorSupport::DeviceSet::GetFanciest (CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id) +{ + Device dev; + + for (NSUInteger i = 0; + i < GetNumDevices(); + i++) + { + Device d(GetDeviceAtIndex(i)); + if (d && d.GetDeviceType() && d.GetDeviceType().GetProductFamilyID() == dev_id) + { + if (!dev) + dev = d; + else + { + if ((d.GetDeviceType().GetModelIdentifier() > dev.GetDeviceType().GetModelIdentifier()) || + d.GetDeviceRuntime().GetVersion() > dev.GetDeviceRuntime().GetVersion()) + dev = d; + } + } + } + + return dev; +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits