300 changes: 300 additions & 0 deletions lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
Original file line number Diff line number Diff line change
@@ -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

81 changes: 81 additions & 0 deletions lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
Original file line number Diff line number Diff line change
@@ -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_
104 changes: 53 additions & 51 deletions lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -61,8 +61,8 @@ PlatformiOSSimulator::Terminate ()
PluginManager::UnregisterPlugin (PlatformiOSSimulator::CreateInstance);
}
}

PlatformDarwin::Terminate ();
PlatformAppleSimulator::Terminate ();
}

PlatformSP
Expand All @@ -73,8 +73,8 @@ PlatformiOSSimulator::CreateInstance (bool force, const ArchSpec *arch)
{
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())
Expand All @@ -84,9 +84,9 @@ PlatformiOSSimulator::CreateInstance (bool force, const ArchSpec *arch)
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;
Expand All @@ -105,9 +105,9 @@ PlatformiOSSimulator::CreateInstance (bool force, const ArchSpec *arch)
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;
Expand All @@ -118,9 +118,9 @@ PlatformiOSSimulator::CreateInstance (bool force, const ArchSpec *arch)
}
}
}
break;
default:
break;
break;
default:
break;
}
}
if (create)
Expand All @@ -147,8 +147,8 @@ PlatformiOSSimulator::GetDescriptionStatic()
/// Default Constructor
//------------------------------------------------------------------
PlatformiOSSimulator::PlatformiOSSimulator () :
PlatformDarwin (true),
m_sdk_directory ()
PlatformAppleSimulator (),
m_sdk_directory ()
{
}

Expand All @@ -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);
}


Expand All @@ -182,29 +183,29 @@ PlatformiOSSimulator::ResolveExecutable (const ModuleSpec &module_spec,
{
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();
Expand All @@ -220,11 +221,11 @@ PlatformiOSSimulator::ResolveExecutable (const ModuleSpec &module_spec,
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())
Expand Down Expand Up @@ -259,11 +260,11 @@ PlatformiOSSimulator::ResolveExecutable (const ModuleSpec &module_spec,
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)
Expand All @@ -281,8 +282,9 @@ EnumerateDirectoryCallback (void *baton, FileSpec::FileType file_type, const Fil


const char *
PlatformiOSSimulator::GetSDKsDirectory()
PlatformiOSSimulator::GetSDKDirectoryAsCString()
{
Mutex::Locker locker (m_mutex);
if (m_sdk_directory.empty())
{
const char *developer_dir = GetDeveloperDirectory();
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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)
{
Expand All @@ -337,28 +339,28 @@ PlatformiOSSimulator::GetSymbolFile (const FileSpec &platform_file,
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());
}
Expand Down Expand Up @@ -392,17 +394,17 @@ PlatformiOSSimulator::GetSharedModule (const ModuleSpec &module_spec,
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;
}

Expand All @@ -414,7 +416,7 @@ PlatformiOSSimulator::FindProcesses (const ProcessInstanceInfoMatch &match_info,
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)
{
Expand All @@ -431,7 +433,7 @@ PlatformiOSSimulator::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &a
{
static const ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
static const ArchSpec platform_arch64(HostInfo::GetArchitecture(HostInfo::eArchKind64));

if (idx == 0)
{
arch = platform_arch;
Expand Down
39 changes: 19 additions & 20 deletions lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -57,59 +57,58 @@ class PlatformiOSSimulator : public PlatformDarwin
{
return 1;
}

//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
lldb_private::Error
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,
lldb::ModuleSP &module_sp,
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
AddClangModuleCompilationOptions (lldb_private::Target *target, std::vector<std::string> &options) override
{
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);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -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_

Large diffs are not rendered by default.