summaryrefslogtreecommitdiff
path: root/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-01-06 20:12:03 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-01-06 20:12:03 +0000
commit9e6d35490a6542f9c97607f93c2ef8ca8e03cbcc (patch)
treedd2a1ddf0476664c2b823409c36cbccd52662ca7 /source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
parent3bd2e91faeb9eeec1aae82c64a3253afff551cfd (diff)
Notes
Diffstat (limited to 'source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp')
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp303
1 files changed, 303 insertions, 0 deletions
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
new file mode 100644
index 0000000000000..eea2844d5649f
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
@@ -0,0 +1,303 @@
+//===-- 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
+#if defined(__APPLE__)
+#include <dlfcn.h>
+#endif
+
+// 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
+