LLDB  mainline
PlatformAppleWatchSimulator.cpp
Go to the documentation of this file.
1 //===-- PlatformAppleWatchSimulator.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 
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/Process.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 using namespace lldb;
27 using namespace lldb_private;
28 
29 namespace lldb_private {
30 class Process;
31 }
32 
33 // Static Variables
35 
36 // Static Functions
39 
40  if (g_initialize_count++ == 0) {
41  PluginManager::RegisterPlugin(
45  }
46 }
47 
49  if (g_initialize_count > 0) {
50  if (--g_initialize_count == 0) {
51  PluginManager::UnregisterPlugin(
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, "PlatformAppleWatchSimulator::%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::WatchOS:
102  break;
103 
104 #if defined(__APPLE__)
105  // Only accept "unknown" for the OS if the host is Apple and it
106  // "unknown" wasn't specified (it was just returned because it was NOT
107  // specified)
108  case llvm::Triple::UnknownOS:
109  create = !arch->TripleOSWasSpecified();
110  break;
111 #endif
112  default:
113  create = false;
114  break;
115  }
116  }
117  } break;
118  default:
119  break;
120  }
121  }
122  if (create) {
123  LLDB_LOGF(log, "PlatformAppleWatchSimulator::%s() creating platform",
124  __FUNCTION__);
125 
126  return PlatformSP(new PlatformAppleWatchSimulator());
127  }
128 
129  LLDB_LOGF(log,
130  "PlatformAppleWatchSimulator::%s() aborting creation of platform",
131  __FUNCTION__);
132 
133  return PlatformSP();
134 }
135 
137  static ConstString g_name("watchos-simulator");
138  return g_name;
139 }
140 
142  return "Apple Watch simulator platform plug-in.";
143 }
144 
145 /// Default Constructor
148  CoreSimulatorSupport::DeviceType::ProductFamilyID::appleWatch) {}
149 
150 /// Destructor.
151 ///
152 /// The destructor is virtual since this class is designed to be
153 /// inherited from by the plug-in instance.
155 
157  Platform::GetStatus(strm);
158  llvm::StringRef sdk_directory = GetSDKDirectoryAsCString();
159  if (!sdk_directory.empty())
160  strm.Printf(" SDK Path: \"%s\"\n", sdk_directory.str().c_str());
161  else
162  strm.PutCString(" SDK Path: error: unable to locate SDK\n");
163 }
164 
166  const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
167  const FileSpecList *module_search_paths_ptr) {
168  Status error;
169  // Nothing special to do here, just use the actual file and architecture
170 
171  ModuleSpec resolved_module_spec(module_spec);
172 
173  // If we have "ls" as the exe_file, resolve the executable loation based on
174  // the current path variables
175  // TODO: resolve bare executables in the Platform SDK
176  // if (!resolved_exe_file.Exists())
177  // resolved_exe_file.ResolveExecutableLocation ();
178 
179  // Resolve any executable within a bundle on MacOSX
180  // TODO: verify that this handles shallow bundles, if not then implement one
181  // ourselves
182  Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
183 
184  if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
185  if (resolved_module_spec.GetArchitecture().IsValid()) {
186  error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
187  NULL, NULL, NULL);
188 
189  if (exe_module_sp && exe_module_sp->GetObjectFile())
190  return error;
191  exe_module_sp.reset();
192  }
193  // No valid architecture was specified or the exact ARM slice wasn't found
194  // so ask the platform for the architectures that we should be using (in
195  // the correct order) and see if we can find a match that way
196  StreamString arch_names;
197  ArchSpec platform_arch;
199  idx, resolved_module_spec.GetArchitecture());
200  ++idx) {
201  // Only match x86 with x86 and x86_64 with x86_64...
202  if (!module_spec.GetArchitecture().IsValid() ||
203  module_spec.GetArchitecture().GetCore() ==
204  resolved_module_spec.GetArchitecture().GetCore()) {
205  error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
206  NULL, NULL, NULL);
207  // Did we find an executable using one of the
208  if (error.Success()) {
209  if (exe_module_sp && exe_module_sp->GetObjectFile())
210  break;
211  else
212  error.SetErrorToGenericError();
213  }
214 
215  if (idx > 0)
216  arch_names.PutCString(", ");
217  arch_names.PutCString(platform_arch.GetArchitectureName());
218  }
219  }
220 
221  if (error.Fail() || !exe_module_sp) {
222  if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
224  "'%s' doesn't contain any '%s' platform architectures: %s",
225  resolved_module_spec.GetFileSpec().GetPath().c_str(),
226  GetPluginName().GetCString(), arch_names.GetString().str().c_str());
227  } else {
229  "'%s' is not readable",
230  resolved_module_spec.GetFileSpec().GetPath().c_str());
231  }
232  }
233  } else {
234  error.SetErrorStringWithFormat("'%s' does not exist",
235  module_spec.GetFileSpec().GetPath().c_str());
236  }
237 
238  return error;
239 }
240 
242  llvm::StringRef sdk;
243  sdk = HostInfo::GetXcodeSDKPath(XcodeSDK("WatchSimulator.Internal.sdk"));
244  if (sdk.empty())
245  sdk = HostInfo::GetXcodeSDKPath(XcodeSDK("WatchSimulator.sdk"));
246  return sdk;
247 }
248 
250  const UUID *uuid_ptr,
251  FileSpec &local_file) {
252  Status error;
253  char platform_file_path[PATH_MAX];
254  if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
255  char resolved_path[PATH_MAX];
256 
257  llvm::StringRef sdk_dir = GetSDKDirectoryAsCString();
258  if (!sdk_dir.empty()) {
259  ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s",
260  sdk_dir.str().c_str(), platform_file_path);
261 
262  // First try in the SDK and see if the file is in there
263  local_file.SetFile(resolved_path, FileSpec::Style::native);
264  FileSystem::Instance().Resolve(local_file);
265  if (FileSystem::Instance().Exists(local_file))
266  return error;
267 
268  // Else fall back to the actual path itself
269  local_file.SetFile(platform_file_path, FileSpec::Style::native);
270  FileSystem::Instance().Resolve(local_file);
271  if (FileSystem::Instance().Exists(local_file))
272  return error;
273  }
275  "unable to locate a platform file for '%s' in platform '%s'",
276  platform_file_path, GetPluginName().GetCString());
277  } else {
278  error.SetErrorString("invalid platform file argument");
279  }
280  return error;
281 }
282 
284  const ModuleSpec &module_spec, lldb_private::Process *process,
285  ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr,
286  ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
287  // For AppleWatch, the SDK files are all cached locally on the host system.
288  // So first we ask for the file in the cached SDK, then we attempt to get a
289  // shared module for the right architecture with the right UUID.
290  Status error;
291  ModuleSpec platform_module_spec(module_spec);
292  const FileSpec &platform_file = module_spec.GetFileSpec();
293  error = GetSymbolFile(platform_file, module_spec.GetUUIDPtr(),
294  platform_module_spec.GetFileSpec());
295  if (error.Success()) {
296  error = ResolveExecutable(platform_module_spec, module_sp,
297  module_search_paths_ptr);
298  } else {
299  const bool always_create = false;
300  error = ModuleList::GetSharedModule(
301  module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
302  did_create_ptr, always_create);
303  }
304  if (module_sp)
305  module_sp->SetPlatformFileSpec(platform_file);
306 
307  return error;
308 }
309 
311  const ProcessInstanceInfoMatch &match_info,
312  ProcessInstanceInfoList &process_infos) {
313  ProcessInstanceInfoList all_osx_process_infos;
314  // First we get all OSX processes
315  const uint32_t n = Host::FindProcesses(match_info, all_osx_process_infos);
316 
317  // Now we filter them down to only the WatchOS triples
318  for (uint32_t i = 0; i < n; ++i) {
319  const ProcessInstanceInfo &proc_info = all_osx_process_infos[i];
320  if (proc_info.GetArchitecture().GetTriple().getOS() ==
321  llvm::Triple::WatchOS) {
322  process_infos.push_back(proc_info);
323  }
324  }
325  return process_infos.size();
326 }
327 
329  uint32_t idx, ArchSpec &arch) {
330  if (idx == 0) {
331  arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
332  if (arch.IsValid()) {
333  arch.GetTriple().setOS(llvm::Triple::WatchOS);
334  arch.GetTriple().setEnvironment(llvm::Triple::Simulator);
335  return true;
336  }
337  }
338 
339  if (idx == 1) {
340  arch = HostInfo::GetArchitecture(HostInfo::eArchKind64);
341  if (arch.IsValid()) {
342  arch.GetTriple().setOS(llvm::Triple::WatchOS);
343  arch.GetTriple().setEnvironment(llvm::Triple::Simulator);
344  return true;
345  }
346  }
347  return false;
348 }
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
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.
Core GetCore() const
Definition: ArchSpec.h:413
lldb_private::ConstString GetPluginName() override
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
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
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
Definition: Host.h:30
static uint32_t g_initialize_count
A file utility class.
Definition: FileSpec.h:56
An architecture specification class.
Definition: ArchSpec.h:33
#define LIBLLDB_LOG_PLATFORM
Definition: Logging.h:39
uint32_t FindProcesses(const lldb_private::ProcessInstanceInfoMatch &match_info, lldb_private::ProcessInstanceInfoList &process_infos) override
Attach to an existing process by process name.
static void Terminate()
Definition: Platform.cpp:152
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:332
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:434
bool TripleVendorWasSpecified() const
Definition: ArchSpec.h:337
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:585
virtual ~PlatformAppleWatchSimulator()
Destructor.
void SetErrorToGenericError()
Set the current error to a generic error.
Definition: Status.cpp:232
static llvm::raw_ostream & error(Stream &strm)
virtual lldb_private::Status GetSymbolFile(const lldb_private::FileSpec &platform_file, const lldb_private::UUID *uuid_ptr, lldb_private::FileSpec &local_file)
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
static void Initialize()
Definition: Platform.cpp:150
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
FileSpec & GetFileSpec()
Definition: ModuleSpec.h:75
void GetStatus(lldb_private::Stream &strm) override
Report the current status for this platform.
PlatformAppleWatchSimulator()
Default Constructor.
ArchSpec & GetArchitecture()
Definition: ModuleSpec.h:111
static lldb_private::ConstString GetPluginNameStatic()
#define LLDB_LOGF(log,...)
Definition: Log.h:249
A uniqued constant string class.
Definition: ConstString.h:40
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
Definition: SBAddress.h:15
bool TripleOSWasSpecified() const
Definition: ArchSpec.h:341
#define PATH_MAX
static lldb::PlatformSP CreateInstance(bool force, const lldb_private::ArchSpec *arch)
lldb_private::Status ResolveExecutable(const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr) override
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
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
An error handling class.
Definition: Status.h:44