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