[Lldb-commits] [lldb] r252112 - Teach LLDB how to directly launch processes on the iOS simulator

Enrico Granata via lldb-commits lldb-commits at lists.llvm.org
Wed Nov 4 16:46:26 PST 2015


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
+ at interface SimDeviceSet
+{}
++ (id) defaultSet;
+ at 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
+ at 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;
+ at 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;
+}




More information about the lldb-commits mailing list