LLDB  mainline
PlatformiOSSimulator.cpp
Go to the documentation of this file.
1 //===-- PlatformiOSSimulator.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 "PlatformiOSSimulator.h"
10 
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/ModuleList.h"
14 #include "lldb/Core/ModuleSpec.h"
16 #include "lldb/Host/Host.h"
17 #include "lldb/Host/HostInfo.h"
18 #include "lldb/Target/Target.h"
19 #include "lldb/Utility/ArchSpec.h"
20 #include "lldb/Utility/FileSpec.h"
21 #include "lldb/Utility/Log.h"
23 #include "lldb/Utility/Status.h"
25 
26 #include "llvm/Support/FileSystem.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 namespace lldb_private {
32 class Process;
33 }
34 
35 // Static Variables
37 
38 // Static Functions
41 
42  if (g_initialize_count++ == 0) {
43  PluginManager::RegisterPlugin(PlatformiOSSimulator::GetPluginNameStatic(),
46  }
47 }
48 
50  if (g_initialize_count > 0) {
51  if (--g_initialize_count == 0) {
52  PluginManager::UnregisterPlugin(PlatformiOSSimulator::CreateInstance);
53  }
54  }
55 
57 }
58 
60  const ArchSpec *arch) {
62  if (log) {
63  const char *arch_name;
64  if (arch && arch->GetArchitectureName())
65  arch_name = arch->GetArchitectureName();
66  else
67  arch_name = "<null>";
68 
69  const char *triple_cstr =
70  arch ? arch->GetTriple().getTriple().c_str() : "<null>";
71 
72  LLDB_LOGF(log, "PlatformiOSSimulator::%s(force=%s, arch={%s,%s})",
73  __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
74  }
75 
76  bool create = force;
77  if (!create && arch && arch->IsValid()) {
78  switch (arch->GetMachine()) {
79  case llvm::Triple::x86_64:
80  case llvm::Triple::x86: {
81  const llvm::Triple &triple = arch->GetTriple();
82  switch (triple.getVendor()) {
83  case llvm::Triple::Apple:
84  create = true;
85  break;
86 
87 #if defined(__APPLE__)
88  // Only accept "unknown" for the vendor if the host is Apple and it
89  // "unknown" wasn't specified (it was just returned because it was NOT
90  // specified)
91  case llvm::Triple::UnknownVendor:
92  create = !arch->TripleVendorWasSpecified();
93  break;
94 #endif
95  default:
96  break;
97  }
98 
99  if (create) {
100  switch (triple.getOS()) {
101  case llvm::Triple::Darwin: // Deprecated, but still support Darwin for
102  // historical reasons
103  case llvm::Triple::MacOSX:
104  case llvm::Triple::IOS: // IOS is not used for simulator triples, but
105  // accept it just in case
106  break;
107 
108 #if defined(__APPLE__)
109  // Only accept "unknown" for the OS if the host is Apple and it
110  // "unknown" wasn't specified (it was just returned because it was NOT
111  // specified)
112  case llvm::Triple::UnknownOS:
113  create = !arch->TripleOSWasSpecified();
114  break;
115 #endif
116  default:
117  create = false;
118  break;
119  }
120  }
121  } break;
122  default:
123  break;
124  }
125  }
126  if (create) {
127  LLDB_LOGF(log, "PlatformiOSSimulator::%s() creating platform",
128  __FUNCTION__);
129 
130  return PlatformSP(new PlatformiOSSimulator());
131  }
132 
133  LLDB_LOGF(log, "PlatformiOSSimulator::%s() aborting creation of platform",
134  __FUNCTION__);
135 
136  return PlatformSP();
137 }
138 
140  static ConstString g_name("ios-simulator");
141  return g_name;
142 }
143 
145  return "iOS simulator platform plug-in.";
146 }
147 
148 /// Default Constructor
151  CoreSimulatorSupport::DeviceType::ProductFamilyID::iPhone) {}
152 
153 /// Destructor.
154 ///
155 /// The destructor is virtual since this class is designed to be
156 /// inherited from by the plug-in instance.
158 
160  Platform::GetStatus(strm);
161  llvm::StringRef sdk_directory = GetSDKDirectoryAsCString();
162  if (!sdk_directory.empty())
163  strm.Printf(" SDK Path: \"%s\"\n", sdk_directory.str().c_str());
164  else
165  strm.PutCString(" SDK Path: error: unable to locate SDK\n");
167 }
168 
170  const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
171  const FileSpecList *module_search_paths_ptr) {
172  Status error;
173  // Nothing special to do here, just use the actual file and architecture
174 
175  ModuleSpec resolved_module_spec(module_spec);
176 
177  // If we have "ls" as the exe_file, resolve the executable loation based on
178  // the current path variables
179  // TODO: resolve bare executables in the Platform SDK
180  // if (!resolved_exe_file.Exists())
181  // resolved_exe_file.ResolveExecutableLocation ();
182 
183  // Resolve any executable within a bundle on MacOSX
184  // TODO: verify that this handles shallow bundles, if not then implement one
185  // ourselves
186  Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
187 
188  if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
189  if (resolved_module_spec.GetArchitecture().IsValid()) {
190  error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
191  NULL, NULL, NULL);
192 
193  if (exe_module_sp && exe_module_sp->GetObjectFile())
194  return error;
195  exe_module_sp.reset();
196  }
197  // No valid architecture was specified or the exact ARM slice wasn't found
198  // so ask the platform for the architectures that we should be using (in
199  // the correct order) and see if we can find a match that way
200  StreamString arch_names;
201  ArchSpec platform_arch;
203  idx, resolved_module_spec.GetArchitecture());
204  ++idx) {
205  // Only match x86 with x86 and x86_64 with x86_64...
206  if (!module_spec.GetArchitecture().IsValid() ||
207  module_spec.GetArchitecture().GetCore() ==
208  resolved_module_spec.GetArchitecture().GetCore()) {
209  error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
210  NULL, NULL, NULL);
211  // Did we find an executable using one of the
212  if (error.Success()) {
213  if (exe_module_sp && exe_module_sp->GetObjectFile())
214  break;
215  else
216  error.SetErrorToGenericError();
217  }
218 
219  if (idx > 0)
220  arch_names.PutCString(", ");
221  arch_names.PutCString(platform_arch.GetArchitectureName());
222  }
223  }
224 
225  if (error.Fail() || !exe_module_sp) {
226  if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
228  "'%s' doesn't contain any '%s' platform architectures: %s",
229  resolved_module_spec.GetFileSpec().GetPath().c_str(),
230  GetPluginName().GetCString(), arch_names.GetString().str().c_str());
231  } else {
233  "'%s' is not readable",
234  resolved_module_spec.GetFileSpec().GetPath().c_str());
235  }
236  }
237  } else {
238  error.SetErrorStringWithFormat("'%s' does not exist",
239  module_spec.GetFileSpec().GetPath().c_str());
240  }
241 
242  return error;
243 }
244 
246  llvm::StringRef sdk;
247  sdk = HostInfo::GetXcodeSDKPath(XcodeSDK("iPhoneSimulator.Internal.sdk"));
248  if (sdk.empty())
249  sdk = HostInfo::GetXcodeSDKPath(XcodeSDK("iPhoneSimulator.sdk"));
250  return sdk;
251 }
252 
254  const UUID *uuid_ptr,
255  FileSpec &local_file) {
256  Status error;
257  char platform_file_path[PATH_MAX];
258  if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
259  char resolved_path[PATH_MAX];
260 
261  llvm::StringRef sdk_dir = GetSDKDirectoryAsCString();
262  if (!sdk_dir.empty()) {
263  ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s",
264  sdk_dir.str().c_str(), platform_file_path);
265 
266  // First try in the SDK and see if the file is in there
267  local_file.SetFile(resolved_path, FileSpec::Style::native);
268  FileSystem::Instance().Resolve(local_file);
269  if (FileSystem::Instance().Exists(local_file))
270  return error;
271 
272  // Else fall back to the actual path itself
273  local_file.SetFile(platform_file_path, FileSpec::Style::native);
274  FileSystem::Instance().Resolve(local_file);
275  if (FileSystem::Instance().Exists(local_file))
276  return error;
277  }
279  "unable to locate a platform file for '%s' in platform '%s'",
280  platform_file_path, GetPluginName().GetCString());
281  } else {
282  error.SetErrorString("invalid platform file argument");
283  }
284  return error;
285 }
286 
288  const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
289  const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
290  bool *did_create_ptr) {
291  // For iOS, the SDK files are all cached locally on the host system. So first
292  // we ask for the file in the cached SDK, then we attempt to get a shared
293  // module for the right architecture with the right UUID.
294  Status error;
295  ModuleSpec platform_module_spec(module_spec);
296  const FileSpec &platform_file = module_spec.GetFileSpec();
297  error = GetSymbolFile(platform_file, module_spec.GetUUIDPtr(),
298  platform_module_spec.GetFileSpec());
299  if (error.Success()) {
300  error = ResolveExecutable(platform_module_spec, module_sp,
301  module_search_paths_ptr);
302  } else {
303  const bool always_create = false;
304  error = ModuleList::GetSharedModule(
305  module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
306  did_create_ptr, always_create);
307  }
308  if (module_sp)
309  module_sp->SetPlatformFileSpec(platform_file);
310 
311  return error;
312 }
313 
314 uint32_t
316  ProcessInstanceInfoList &process_infos) {
317  ProcessInstanceInfoList all_osx_process_infos;
318  // First we get all OSX processes
319  const uint32_t n = Host::FindProcesses(match_info, all_osx_process_infos);
320 
321  // Now we filter them down to only the iOS triples
322  for (uint32_t i = 0; i < n; ++i) {
323  const ProcessInstanceInfo &proc_info = all_osx_process_infos[i];
324  if (proc_info.GetArchitecture().GetTriple().getOS() == llvm::Triple::IOS) {
325  process_infos.push_back(proc_info);
326  }
327  }
328  return process_infos.size();
329 }
330 
332  ArchSpec &arch) {
333  static const ArchSpec platform_arch(
334  HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
335  static const ArchSpec platform_arch64(
336  HostInfo::GetArchitecture(HostInfo::eArchKind64));
337 
338  if (idx == 0) {
339  arch = platform_arch;
340  if (arch.IsValid()) {
341  arch.GetTriple().setOS(llvm::Triple::IOS);
342  arch.GetTriple().setEnvironment(llvm::Triple::Simulator);
343  return true;
344  }
345  } else {
346  if (platform_arch.IsExactMatch(platform_arch64)) {
347  // This macosx platform supports both 32 and 64 bit.
348  if (idx == 1) {
349  // 32/64: return "x86_64-apple-macosx" for architecture 1
350  arch = platform_arch64;
351  return true;
352  } else if (idx == 2 || idx == 3) {
353  arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
354  if (arch.IsValid()) {
355  if (idx == 2)
356  arch.GetTriple().setOS(llvm::Triple::IOS);
357  // 32/64: return "i386-apple-ios" for architecture 2 32/64: return
358  // "i386-apple-macosx" for architecture 3
359  return true;
360  }
361  }
362  } else if (idx == 1) {
363  // This macosx platform supports only 32 bit, so return the *-apple-
364  // macosx version
365  arch = platform_arch;
366  return true;
367  }
368  }
369  return false;
370 }
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
bool IsExactMatch(const ArchSpec &rhs) const
Compare an ArchSpec to another ArchSpec, requiring an exact cpu type match between them...
Definition: ArchSpec.cpp:968
Core GetCore() const
Definition: ArchSpec.h:413
virtual lldb_private::Status GetSymbolFile(const lldb_private::FileSpec &platform_file, const lldb_private::UUID *uuid_ptr, lldb_private::FileSpec &local_file)
A class that represents a running process on the host machine.
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
Definition: Host.h:30
llvm::StringRef GetSDKDirectoryAsCString()
~PlatformiOSSimulator() override
Destructor.
A file utility class.
Definition: FileSpec.h:56
An architecture specification class.
Definition: ArchSpec.h:33
#define LIBLLDB_LOG_PLATFORM
Definition: Logging.h:39
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:332
lldb_private::ConstString GetPluginName() override
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:434
lldb_private::Status ResolveExecutable(const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr) override
lldb_private::Status 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
bool TripleVendorWasSpecified() const
Definition: ArchSpec.h:337
void GetStatus(lldb_private::Stream &strm) override
Report the current status for this platform.
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:585
void SetErrorToGenericError()
Set the current error to a generic error.
Definition: Status.cpp:232
static llvm::raw_ostream & error(Stream &strm)
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
void GetStatus(lldb_private::Stream &strm) override
Report the current status for this platform.
llvm::StringRef GetString() const
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:242
A plug-in interface definition class for debugging a process.
Definition: Process.h:362
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
ArchSpec & GetArchitecture()
Definition: ProcessInfo.h:62
bool Success() const
Test for success condition.
Definition: Status.cpp:288
uint32_t FindProcesses(const lldb_private::ProcessInstanceInfoMatch &match_info, lldb_private::ProcessInstanceInfoList &process_infos) override
Attach to an existing process by process name.
FileSpec & GetFileSpec()
Definition: ModuleSpec.h:75
ArchSpec & GetArchitecture()
Definition: ModuleSpec.h:111
#define LLDB_LOGF(log,...)
Definition: Log.h:249
A uniqued constant string class.
Definition: ConstString.h:40
static const char * GetDescriptionStatic()
bool Fail() const
Test for error condition.
Definition: Status.cpp:182
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:246
An abstraction for Xcode-style SDKs that works like ArchSpec.
Definition: XcodeSDK.h:24
bool GetSupportedArchitectureAtIndex(uint32_t idx, lldb_private::ArchSpec &arch) override
Get the platform&#39;s supported architectures in the order in which they should be searched.
Definition: SBAddress.h:15
bool TripleOSWasSpecified() const
Definition: ArchSpec.h:341
static lldb_private::ConstString GetPluginNameStatic()
#define PATH_MAX
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:256
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:174
#define NULL
PlatformiOSSimulator()
Default Constructor.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:348
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:714
static uint32_t g_initialize_count
static lldb::PlatformSP CreateInstance(bool force, const lldb_private::ArchSpec *arch)
An error handling class.
Definition: Status.h:44