Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- PlatformAppleSimulator.cpp ----------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "PlatformAppleSimulator.h"
10
11
#if defined(__APPLE__)
12
#include <dlfcn.h>
13
#endif
14
15
#include "lldb/Core/Module.h"
16
#include "lldb/Core/PluginManager.h"
17
#include "lldb/Host/HostInfo.h"
18
#include "lldb/Host/PseudoTerminal.h"
19
#include "lldb/Target/Process.h"
20
#include "lldb/Utility/LLDBAssert.h"
21
#include "lldb/Utility/Log.h"
22
#include "lldb/Utility/Status.h"
23
#include "lldb/Utility/StreamString.h"
24
25
#include "llvm/Support/Threading.h"
26
27
#include <mutex>
28
#include <thread>
29
30
using namespace lldb;
31
using namespace lldb_private;
32
33
#if !defined(__APPLE__)
34
#define UNSUPPORTED_ERROR ("Apple simulators aren't supported on this platform")
35
#endif
36
37
/// Default Constructor
38
PlatformAppleSimulator::PlatformAppleSimulator(
39
    const char *class_name, const char *description, ConstString plugin_name,
40
    llvm::Triple::OSType preferred_os,
41
    llvm::SmallVector<llvm::StringRef, 4> supported_triples,
42
    llvm::StringRef sdk, lldb_private::XcodeSDK::Type sdk_type,
43
    CoreSimulatorSupport::DeviceType::ProductFamilyID kind)
44
    : PlatformDarwin(true), m_class_name(class_name),
45
      m_description(description), m_plugin_name(plugin_name), m_kind(kind),
46
      m_os_type(preferred_os), m_supported_triples(supported_triples),
47
8
      m_sdk(sdk), m_sdk_type(sdk_type) {}
48
49
/// Destructor.
50
///
51
/// The destructor is virtual since this class is designed to be
52
/// inherited from by the plug-in instance.
53
8
PlatformAppleSimulator::~PlatformAppleSimulator() = default;
54
55
lldb_private::Status PlatformAppleSimulator::LaunchProcess(
56
0
    lldb_private::ProcessLaunchInfo &launch_info) {
57
0
#if defined(__APPLE__)
58
0
  LoadCoreSimulator();
59
0
  CoreSimulatorSupport::Device device(GetSimulatorDevice());
60
61
0
  if (device.GetState() != CoreSimulatorSupport::Device::State::Booted) {
62
0
    Status boot_err;
63
0
    device.Boot(boot_err);
64
0
    if (boot_err.Fail())
65
0
      return boot_err;
66
0
  }
67
68
0
  auto spawned = device.Spawn(launch_info);
69
70
0
  if (spawned) {
71
0
    launch_info.SetProcessID(spawned.GetPID());
72
0
    return Status();
73
0
  } else
74
0
    return spawned.GetError();
75
#else
76
  Status err;
77
  err.SetErrorString(UNSUPPORTED_ERROR);
78
  return err;
79
#endif
80
0
}
81
82
0
void PlatformAppleSimulator::GetStatus(Stream &strm) {
83
0
  Platform::GetStatus(strm);
84
0
  if (!m_sdk.empty())
85
0
    strm << "  SDK Path: \"" << m_sdk << "\"\n";
86
0
  else
87
0
    strm << "  SDK Path: error: unable to locate SDK\n";
88
89
0
#if defined(__APPLE__)
90
  // This will get called by subclasses, so just output status on the current
91
  // simulator
92
0
  PlatformAppleSimulator::LoadCoreSimulator();
93
94
0
  std::string developer_dir = HostInfo::GetXcodeDeveloperDirectory().GetPath();
95
0
  CoreSimulatorSupport::DeviceSet devices =
96
0
      CoreSimulatorSupport::DeviceSet::GetAvailableDevices(
97
0
          developer_dir.c_str());
98
0
  const size_t num_devices = devices.GetNumDevices();
99
0
  if (num_devices) {
100
0
    strm.Printf("Available devices:\n");
101
0
    for (size_t i = 0; i < num_devices; ++i) {
102
0
      CoreSimulatorSupport::Device device = devices.GetDeviceAtIndex(i);
103
0
      strm << "   " << device.GetUDID() << ": " << device.GetName() << "\n";
104
0
    }
105
106
0
    if (m_device.hasValue() && m_device->operator bool()) {
107
0
      strm << "Current device: " << m_device->GetUDID() << ": "
108
0
           << m_device->GetName();
109
0
      if (m_device->GetState() == CoreSimulatorSupport::Device::State::Booted) {
110
0
        strm << " state = booted";
111
0
      }
112
0
      strm << "\nType \"platform connect <ARG>\" where <ARG> is a device "
113
0
              "UDID or a device name to disconnect and connect to a "
114
0
              "different device.\n";
115
116
0
    } else {
117
0
      strm << "No current device is selected, \"platform connect <ARG>\" "
118
0
              "where <ARG> is a device UDID or a device name to connect to "
119
0
              "a specific device.\n";
120
0
    }
121
122
0
  } else {
123
0
    strm << "No devices are available.\n";
124
0
  }
125
#else
126
  strm << UNSUPPORTED_ERROR;
127
#endif
128
0
}
129
130
0
Status PlatformAppleSimulator::ConnectRemote(Args &args) {
131
0
#if defined(__APPLE__)
132
0
  Status error;
133
0
  if (args.GetArgumentCount() == 1) {
134
0
    if (m_device)
135
0
      DisconnectRemote();
136
0
    PlatformAppleSimulator::LoadCoreSimulator();
137
0
    const char *arg_cstr = args.GetArgumentAtIndex(0);
138
0
    if (arg_cstr) {
139
0
      std::string arg_str(arg_cstr);
140
0
      std::string developer_dir = HostInfo::GetXcodeDeveloperDirectory().GetPath();
141
0
      CoreSimulatorSupport::DeviceSet devices =
142
0
          CoreSimulatorSupport::DeviceSet::GetAvailableDevices(
143
0
              developer_dir.c_str());
144
0
      devices.ForEach(
145
0
          [this, &arg_str](const CoreSimulatorSupport::Device &device) -> bool {
146
0
            if (arg_str == device.GetUDID() || arg_str == device.GetName()) {
147
0
              m_device = device;
148
0
              return false; // Stop iterating
149
0
            } else {
150
0
              return true; // Keep iterating
151
0
            }
152
0
          });
153
0
      if (!m_device)
154
0
        error.SetErrorStringWithFormat(
155
0
            "no device with UDID or name '%s' was found", arg_cstr);
156
0
    }
157
0
  } else {
158
0
    error.SetErrorString("this command take a single UDID argument of the "
159
0
                         "device you want to connect to.");
160
0
  }
161
0
  return error;
162
#else
163
  Status err;
164
  err.SetErrorString(UNSUPPORTED_ERROR);
165
  return err;
166
#endif
167
0
}
168
169
0
Status PlatformAppleSimulator::DisconnectRemote() {
170
0
#if defined(__APPLE__)
171
0
  m_device.reset();
172
0
  return Status();
173
#else
174
  Status err;
175
  err.SetErrorString(UNSUPPORTED_ERROR);
176
  return err;
177
#endif
178
0
}
179
180
lldb::ProcessSP
181
PlatformAppleSimulator::DebugProcess(ProcessLaunchInfo &launch_info,
182
                                     Debugger &debugger, Target &target,
183
0
                                     Status &error) {
184
0
#if defined(__APPLE__)
185
0
  ProcessSP process_sp;
186
  // Make sure we stop at the entry point
187
0
  launch_info.GetFlags().Set(eLaunchFlagDebug);
188
  // We always launch the process we are going to debug in a separate process
189
  // group, since then we can handle ^C interrupts ourselves w/o having to
190
  // worry about the target getting them as well.
191
0
  launch_info.SetLaunchInSeparateProcessGroup(true);
192
193
0
  error = LaunchProcess(launch_info);
194
0
  if (error.Success()) {
195
0
    if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
196
0
      ProcessAttachInfo attach_info(launch_info);
197
0
      process_sp = Attach(attach_info, debugger, &target, error);
198
0
      if (process_sp) {
199
0
        launch_info.SetHijackListener(attach_info.GetHijackListener());
200
201
        // Since we attached to the process, it will think it needs to detach
202
        // if the process object just goes away without an explicit call to
203
        // Process::Kill() or Process::Detach(), so let it know to kill the
204
        // process if this happens.
205
0
        process_sp->SetShouldDetach(false);
206
207
        // If we didn't have any file actions, the pseudo terminal might have
208
        // been used where the secondary side was given as the file to open for
209
        // stdin/out/err after we have already opened the primary so we can
210
        // read/write stdin/out/err.
211
0
        int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();
212
0
        if (pty_fd != PseudoTerminal::invalid_fd) {
213
0
          process_sp->SetSTDIOFileDescriptor(pty_fd);
214
0
        }
215
0
      }
216
0
    }
217
0
  }
218
219
0
  return process_sp;
220
#else
221
  return ProcessSP();
222
#endif
223
0
}
224
225
0
FileSpec PlatformAppleSimulator::GetCoreSimulatorPath() {
226
0
#if defined(__APPLE__)
227
0
  std::lock_guard<std::mutex> guard(m_core_sim_path_mutex);
228
0
  if (!m_core_simulator_framework_path.hasValue()) {
229
0
    m_core_simulator_framework_path =
230
0
        FileSpec("/Library/Developer/PrivateFrameworks/CoreSimulator.framework/"
231
0
                 "CoreSimulator");
232
0
    FileSystem::Instance().Resolve(*m_core_simulator_framework_path);
233
0
  }
234
0
  return m_core_simulator_framework_path.getValue();
235
#else
236
  return FileSpec();
237
#endif
238
0
}
239
240
0
void PlatformAppleSimulator::LoadCoreSimulator() {
241
0
#if defined(__APPLE__)
242
0
  static llvm::once_flag g_load_core_sim_flag;
243
0
  llvm::call_once(g_load_core_sim_flag, [this] {
244
0
    const std::string core_sim_path(GetCoreSimulatorPath().GetPath());
245
0
    if (core_sim_path.size())
246
0
      dlopen(core_sim_path.c_str(), RTLD_LAZY);
247
0
  });
248
0
#endif
249
0
}
250
251
#if defined(__APPLE__)
252
0
CoreSimulatorSupport::Device PlatformAppleSimulator::GetSimulatorDevice() {
253
0
  if (!m_device.hasValue()) {
254
0
    const CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id = m_kind;
255
0
    std::string developer_dir = HostInfo::GetXcodeDeveloperDirectory().GetPath();
256
0
    m_device = CoreSimulatorSupport::DeviceSet::GetAvailableDevices(
257
0
                   developer_dir.c_str())
258
0
                   .GetFanciest(dev_id);
259
0
  }
260
261
0
  if (m_device.hasValue())
262
0
    return m_device.getValue();
263
0
  else
264
0
    return CoreSimulatorSupport::Device();
265
0
}
266
#endif
267
268
16
std::vector<ArchSpec> PlatformAppleSimulator::GetSupportedArchitectures() {
269
16
  std::vector<ArchSpec> result(m_supported_triples.size());
270
16
  llvm::transform(m_supported_triples, result.begin(),
271
44
                  [](llvm::StringRef triple) { return ArchSpec(triple); });
272
16
  return result;
273
16
}
274
275
PlatformSP PlatformAppleSimulator::CreateInstance(
276
    const char *class_name, const char *description, ConstString plugin_name,
277
    llvm::SmallVector<llvm::Triple::ArchType, 4> supported_arch,
278
    llvm::Triple::OSType preferred_os,
279
    llvm::SmallVector<llvm::Triple::OSType, 4> supported_os,
280
    llvm::SmallVector<llvm::StringRef, 4> supported_triples,
281
    llvm::StringRef sdk, lldb_private::XcodeSDK::Type sdk_type,
282
    CoreSimulatorSupport::DeviceType::ProductFamilyID kind, bool force,
283
73
    const ArchSpec *arch) {
284
73
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
285
73
  if (log) {
286
0
    const char *arch_name;
287
0
    if (arch && arch->GetArchitectureName())
288
0
      arch_name = arch->GetArchitectureName();
289
0
    else
290
0
      arch_name = "<null>";
291
292
0
    const char *triple_cstr =
293
0
        arch ? arch->GetTriple().getTriple().c_str() : "<null>";
294
295
0
    LLDB_LOGF(log, "%s::%s(force=%s, arch={%s,%s})", class_name, __FUNCTION__,
296
0
              force ? "true" : "false", arch_name, triple_cstr);
297
0
  }
298
299
73
  bool create = force;
300
73
  if (!create && 
arch70
&&
arch->IsValid()70
) {
301
70
    if (std::count(supported_arch.begin(), supported_arch.end(),
302
70
                   arch->GetMachine())) {
303
22
      const llvm::Triple &triple = arch->GetTriple();
304
22
      switch (triple.getVendor()) {
305
10
      case llvm::Triple::Apple:
306
10
        create = true;
307
10
        break;
308
309
0
#if defined(__APPLE__)
310
      // Only accept "unknown" for the vendor if the host is Apple and if
311
      // "unknown" wasn't specified (it was just returned because it was NOT
312
      // specified)
313
0
      case llvm::Triple::UnknownVendor:
314
0
        create = !arch->TripleVendorWasSpecified();
315
0
        break;
316
0
#endif
317
12
      default:
318
12
        break;
319
22
      }
320
321
22
      if (create) {
322
10
        if (std::count(supported_os.begin(), supported_os.end(), triple.getOS()))
323
5
          create = true;
324
5
#if defined(__APPLE__)
325
        // Only accept "unknown" for the OS if the host is Apple and it
326
        // "unknown" wasn't specified (it was just returned because it was NOT
327
        // specified)
328
5
        else if (triple.getOS() == llvm::Triple::UnknownOS)
329
0
          create = !arch->TripleOSWasSpecified();
330
5
#endif
331
5
        else
332
5
          create = false;
333
10
      }
334
22
    }
335
70
  }
336
73
  if (create) {
337
8
    LLDB_LOGF(log, "%s::%s() creating platform", class_name, __FUNCTION__);
338
339
8
    return PlatformSP(new PlatformAppleSimulator(
340
8
        class_name, description, plugin_name, preferred_os, supported_triples,
341
8
        sdk, sdk_type, kind));
342
8
  }
343
344
65
  LLDB_LOGF(log, "%s::%s() aborting creation of platform", class_name,
345
65
            __FUNCTION__);
346
347
65
  return PlatformSP();
348
73
}
349
350
Status PlatformAppleSimulator::ResolveExecutable(
351
    const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
352
0
    const FileSpecList *module_search_paths_ptr) {
353
0
  Status error;
354
  // Nothing special to do here, just use the actual file and architecture
355
356
0
  ModuleSpec resolved_module_spec(module_spec);
357
358
  // If we have "ls" as the exe_file, resolve the executable loation based on
359
  // the current path variables
360
  // TODO: resolve bare executables in the Platform SDK
361
  //    if (!resolved_exe_file.Exists())
362
  //        resolved_exe_file.ResolveExecutableLocation ();
363
364
  // Resolve any executable within a bundle on MacOSX
365
  // TODO: verify that this handles shallow bundles, if not then implement one
366
  // ourselves
367
0
  Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
368
369
0
  if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
370
0
    if (resolved_module_spec.GetArchitecture().IsValid()) {
371
0
      error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
372
0
                                          NULL, NULL, NULL);
373
374
0
      if (exe_module_sp && exe_module_sp->GetObjectFile())
375
0
        return error;
376
0
      exe_module_sp.reset();
377
0
    }
378
    // No valid architecture was specified or the exact ARM slice wasn't found
379
    // so ask the platform for the architectures that we should be using (in
380
    // the correct order) and see if we can find a match that way
381
0
    StreamString arch_names;
382
0
    llvm::ListSeparator LS;
383
0
    ArchSpec platform_arch;
384
0
    for (const ArchSpec &arch : GetSupportedArchitectures()) {
385
0
      resolved_module_spec.GetArchitecture() = arch;
386
387
      // Only match x86 with x86 and x86_64 with x86_64...
388
0
      if (!module_spec.GetArchitecture().IsValid() ||
389
0
          module_spec.GetArchitecture().GetCore() ==
390
0
              resolved_module_spec.GetArchitecture().GetCore()) {
391
0
        error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
392
0
                                            NULL, NULL, NULL);
393
        // Did we find an executable using one of the
394
0
        if (error.Success()) {
395
0
          if (exe_module_sp && exe_module_sp->GetObjectFile())
396
0
            break;
397
0
          else
398
0
            error.SetErrorToGenericError();
399
0
        }
400
401
0
        arch_names << LS << platform_arch.GetArchitectureName();
402
0
      }
403
0
    }
404
405
0
    if (error.Fail() || !exe_module_sp) {
406
0
      if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
407
0
        error.SetErrorStringWithFormatv(
408
0
            "'{0}' doesn't contain any '{1}' platform architectures: {2}",
409
0
            resolved_module_spec.GetFileSpec(), GetPluginName(),
410
0
            arch_names.GetString());
411
0
      } else {
412
0
        error.SetErrorStringWithFormat(
413
0
            "'%s' is not readable",
414
0
            resolved_module_spec.GetFileSpec().GetPath().c_str());
415
0
      }
416
0
    }
417
0
  } else {
418
0
    error.SetErrorStringWithFormat("'%s' does not exist",
419
0
                                   module_spec.GetFileSpec().GetPath().c_str());
420
0
  }
421
422
0
  return error;
423
0
}
424
425
Status PlatformAppleSimulator::GetSymbolFile(const FileSpec &platform_file,
426
                                             const UUID *uuid_ptr,
427
0
                                             FileSpec &local_file) {
428
0
  Status error;
429
0
  char platform_file_path[PATH_MAX];
430
0
  if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
431
0
    char resolved_path[PATH_MAX];
432
433
0
    if (!m_sdk.empty()) {
434
0
      ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s",
435
0
                 m_sdk.str().c_str(), platform_file_path);
436
437
      // First try in the SDK and see if the file is in there
438
0
      local_file.SetFile(resolved_path, FileSpec::Style::native);
439
0
      FileSystem::Instance().Resolve(local_file);
440
0
      if (FileSystem::Instance().Exists(local_file))
441
0
        return error;
442
443
      // Else fall back to the actual path itself
444
0
      local_file.SetFile(platform_file_path, FileSpec::Style::native);
445
0
      FileSystem::Instance().Resolve(local_file);
446
0
      if (FileSystem::Instance().Exists(local_file))
447
0
        return error;
448
0
    }
449
0
    error.SetErrorStringWithFormatv(
450
0
        "unable to locate a platform file for '{0}' in platform '{1}'",
451
0
        platform_file_path, GetPluginName());
452
0
  } else {
453
0
    error.SetErrorString("invalid platform file argument");
454
0
  }
455
0
  return error;
456
0
}
457
458
Status PlatformAppleSimulator::GetSharedModule(
459
    const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
460
    const FileSpecList *module_search_paths_ptr,
461
0
    llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) {
462
  // For iOS/tvOS/watchOS, the SDK files are all cached locally on the
463
  // host system. So first we ask for the file in the cached SDK, then
464
  // we attempt to get a shared module for the right architecture with
465
  // the right UUID.
466
0
  Status error;
467
0
  ModuleSpec platform_module_spec(module_spec);
468
0
  const FileSpec &platform_file = module_spec.GetFileSpec();
469
0
  error = GetSymbolFile(platform_file, module_spec.GetUUIDPtr(),
470
0
                        platform_module_spec.GetFileSpec());
471
0
  if (error.Success()) {
472
0
    error = ResolveExecutable(platform_module_spec, module_sp,
473
0
                              module_search_paths_ptr);
474
0
  } else {
475
0
    const bool always_create = false;
476
0
    error = ModuleList::GetSharedModule(module_spec, module_sp,
477
0
                                        module_search_paths_ptr, old_modules,
478
0
                                        did_create_ptr, always_create);
479
0
  }
480
0
  if (module_sp)
481
0
    module_sp->SetPlatformFileSpec(platform_file);
482
483
0
  return error;
484
0
}
485
486
uint32_t PlatformAppleSimulator::FindProcesses(
487
    const ProcessInstanceInfoMatch &match_info,
488
0
    ProcessInstanceInfoList &process_infos) {
489
0
  ProcessInstanceInfoList all_osx_process_infos;
490
  // First we get all OSX processes
491
0
  const uint32_t n = Host::FindProcesses(match_info, all_osx_process_infos);
492
493
  // Now we filter them down to only the matching triples.
494
0
  for (uint32_t i = 0; i < n; ++i) {
495
0
    const ProcessInstanceInfo &proc_info = all_osx_process_infos[i];
496
0
    const llvm::Triple &triple = proc_info.GetArchitecture().GetTriple();
497
0
    if (triple.getOS() == m_os_type &&
498
0
        triple.getEnvironment() == llvm::Triple::Simulator) {
499
0
      process_infos.push_back(proc_info);
500
0
    }
501
0
  }
502
0
  return process_infos.size();
503
0
}
504
505
/// Whether to skip creating a simulator platform.
506
247
static bool shouldSkipSimulatorPlatform(bool force, const ArchSpec *arch) {
507
  // If the arch is known not to specify a simulator environment, skip creating
508
  // the simulator platform (we can create it later if there's a matching arch).
509
  // This avoids very slow xcrun queries for non-simulator archs (the slowness
510
  // is due to xcrun not caching negative queries (rdar://74882205)).
511
247
  return !force && 
arch244
&&
arch->IsValid()244
&&
512
247
         
!arch->TripleEnvironmentWasSpecified()244
;
513
247
}
514
515
static llvm::StringRef GetXcodeSDKDir(std::string preferred,
516
73
                                      std::string secondary) {
517
73
  llvm::StringRef sdk;
518
73
  sdk = HostInfo::GetXcodeSDKPath(XcodeSDK(std::move(preferred)));
519
73
  if (sdk.empty())
520
73
    sdk = HostInfo::GetXcodeSDKPath(XcodeSDK(std::move(secondary)));
521
73
  return sdk;
522
73
}
523
524
static const char *g_ios_plugin_name = "ios-simulator";
525
static const char *g_ios_description = "iPhone simulator platform plug-in.";
526
527
/// IPhone Simulator Plugin.
528
struct PlatformiOSSimulator {
529
3.44k
  static void Initialize() {
530
3.44k
    PluginManager::RegisterPlugin(g_ios_plugin_name, g_ios_description,
531
3.44k
                                  PlatformiOSSimulator::CreateInstance);
532
3.44k
  }
533
534
3.43k
  static void Terminate() {
535
3.43k
    PluginManager::UnregisterPlugin(PlatformiOSSimulator::CreateInstance);
536
3.43k
  }
537
538
84
  static PlatformSP CreateInstance(bool force, const ArchSpec *arch) {
539
84
    if (shouldSkipSimulatorPlatform(force, arch))
540
58
      return nullptr;
541
26
    llvm::StringRef sdk;
542
26
    sdk = HostInfo::GetXcodeSDKPath(XcodeSDK("iPhoneSimulator.Internal.sdk"));
543
26
    if (sdk.empty())
544
26
      sdk = HostInfo::GetXcodeSDKPath(XcodeSDK("iPhoneSimulator.sdk"));
545
546
26
    return PlatformAppleSimulator::CreateInstance(
547
26
        "PlatformiOSSimulator", g_ios_description,
548
26
        ConstString(g_ios_plugin_name),
549
26
        {llvm::Triple::aarch64, llvm::Triple::x86_64, llvm::Triple::x86},
550
26
        llvm::Triple::IOS,
551
26
        {// Deprecated, but still support Darwin for historical reasons.
552
26
         llvm::Triple::Darwin, llvm::Triple::MacOSX,
553
         // IOS is not used for simulator triples, but accept it just in
554
         // case.
555
26
         llvm::Triple::IOS},
556
26
        {
557
26
#ifdef __APPLE__
558
#if __arm64__
559
          "arm64e-apple-ios-simulator", "arm64-apple-ios-simulator",
560
              "x86_64-apple-ios-simulator", "x86_64h-apple-ios-simulator",
561
#else
562
26
          "x86_64h-apple-ios-simulator", "x86_64-apple-ios-simulator",
563
26
              "i386-apple-ios-simulator",
564
26
#endif
565
26
#endif
566
26
        },
567
26
        GetXcodeSDKDir("iPhoneSimulator.Internal.sdk", "iPhoneSimulator.sdk"),
568
26
        XcodeSDK::Type::iPhoneSimulator,
569
26
        CoreSimulatorSupport::DeviceType::ProductFamilyID::iPhone, force, arch);
570
84
  }
571
};
572
573
static const char *g_tvos_plugin_name = "tvos-simulator";
574
static const char *g_tvos_description = "tvOS simulator platform plug-in.";
575
576
/// Apple TV Simulator Plugin.
577
struct PlatformAppleTVSimulator {
578
3.44k
  static void Initialize() {
579
3.44k
    PluginManager::RegisterPlugin(g_tvos_plugin_name, g_tvos_description,
580
3.44k
                                  PlatformAppleTVSimulator::CreateInstance);
581
3.44k
  }
582
583
3.43k
  static void Terminate() {
584
3.43k
    PluginManager::UnregisterPlugin(PlatformAppleTVSimulator::CreateInstance);
585
3.43k
  }
586
587
82
  static PlatformSP CreateInstance(bool force, const ArchSpec *arch) {
588
82
    if (shouldSkipSimulatorPlatform(force, arch))
589
58
      return nullptr;
590
24
    return PlatformAppleSimulator::CreateInstance(
591
24
        "PlatformAppleTVSimulator", g_tvos_description,
592
24
        ConstString(g_tvos_plugin_name),
593
24
        {llvm::Triple::aarch64, llvm::Triple::x86_64}, llvm::Triple::TvOS,
594
24
        {llvm::Triple::TvOS},
595
24
        {
596
24
#ifdef __APPLE__
597
#if __arm64__
598
          "arm64e-apple-tvos-simulator", "arm64-apple-tvos-simulator",
599
              "x86_64h-apple-tvos-simulator", "x86_64-apple-tvos-simulator",
600
#else
601
24
          "x86_64h-apple-tvos-simulator", "x86_64-apple-tvos-simulator",
602
24
#endif
603
24
#endif
604
24
        },
605
24
        GetXcodeSDKDir("AppleTVSimulator.Internal.sdk", "AppleTVSimulator.sdk"),
606
24
        XcodeSDK::Type::AppleTVSimulator,
607
24
        CoreSimulatorSupport::DeviceType::ProductFamilyID::appleTV, force,
608
24
        arch);
609
82
  }
610
};
611
612
613
static const char *g_watchos_plugin_name = "watchos-simulator";
614
static const char *g_watchos_description =
615
    "Apple Watch simulator platform plug-in.";
616
617
/// Apple Watch Simulator Plugin.
618
struct PlatformAppleWatchSimulator {
619
3.44k
  static void Initialize() {
620
3.44k
    PluginManager::RegisterPlugin(g_watchos_plugin_name, g_watchos_description,
621
3.44k
                                  PlatformAppleWatchSimulator::CreateInstance);
622
3.44k
  }
623
624
3.43k
  static void Terminate() {
625
3.43k
    PluginManager::UnregisterPlugin(
626
3.43k
        PlatformAppleWatchSimulator::CreateInstance);
627
3.43k
  }
628
629
81
  static PlatformSP CreateInstance(bool force, const ArchSpec *arch) {
630
81
    if (shouldSkipSimulatorPlatform(force, arch))
631
58
      return nullptr;
632
23
    return PlatformAppleSimulator::CreateInstance(
633
23
        "PlatformAppleWatchSimulator", g_watchos_description,
634
23
        ConstString(g_watchos_plugin_name),
635
23
        {llvm::Triple::aarch64, llvm::Triple::x86_64, llvm::Triple::x86},
636
23
        llvm::Triple::WatchOS, {llvm::Triple::WatchOS},
637
23
        {
638
23
#ifdef __APPLE__
639
#if __arm64__
640
          "arm64e-apple-watchos-simulator", "arm64-apple-watchos-simulator",
641
#else
642
23
          "x86_64-apple-watchos-simulator", "x86_64h-apple-watchos-simulator",
643
23
              "i386-apple-watchos-simulator",
644
23
#endif
645
23
#endif
646
23
        },
647
23
        GetXcodeSDKDir("WatchSimulator.Internal.sdk", "WatchSimulator.sdk"),
648
23
        XcodeSDK::Type::WatchSimulator,
649
23
        CoreSimulatorSupport::DeviceType::ProductFamilyID::appleWatch, force,
650
23
        arch);
651
81
  }
652
};
653
654
655
static unsigned g_initialize_count = 0;
656
657
// Static Functions
658
3.44k
void PlatformAppleSimulator::Initialize() {
659
3.44k
  if (g_initialize_count++ == 0) {
660
3.44k
    PlatformDarwin::Initialize();
661
3.44k
    PlatformiOSSimulator::Initialize();
662
3.44k
    PlatformAppleTVSimulator::Initialize();
663
3.44k
    PlatformAppleWatchSimulator::Initialize();
664
3.44k
  }
665
3.44k
}
666
667
3.43k
void PlatformAppleSimulator::Terminate() {
668
3.43k
  if (g_initialize_count > 0)
669
3.43k
    if (--g_initialize_count == 0) {
670
3.43k
      PlatformAppleWatchSimulator::Terminate();
671
3.43k
      PlatformAppleTVSimulator::Terminate();
672
3.43k
      PlatformiOSSimulator::Terminate();
673
3.43k
      PlatformDarwin::Terminate();
674
3.43k
    }
675
3.43k
}
676