diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 |
commit | 9e6d35490a6542f9c97607f93c2ef8ca8e03cbcc (patch) | |
tree | dd2a1ddf0476664c2b823409c36cbccd52662ca7 /source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp | |
parent | 3bd2e91faeb9eeec1aae82c64a3253afff551cfd (diff) |
Notes
Diffstat (limited to 'source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp')
-rw-r--r-- | source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp | 303 |
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 + |