LLDB  mainline
PlatformAppleTVSimulator.cpp
Go to the documentation of this file.
1 //===-- PlatformAppleTVSimulator.cpp ----------------------------*- C++ -*-===//
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/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(
47  }
48 }
49 
51  if (g_initialize_count > 0) {
52  if (--g_initialize_count == 0) {
53  PluginManager::UnregisterPlugin(PlatformAppleTVSimulator::CreateInstance);
54  }
55  }
56 
58 }
59 
61  const ArchSpec *arch) {
63  if (log) {
64  const char *arch_name;
65  if (arch && arch->GetArchitectureName())
66  arch_name = arch->GetArchitectureName();
67  else
68  arch_name = "<null>";
69 
70  const char *triple_cstr =
71  arch ? arch->GetTriple().getTriple().c_str() : "<null>";
72 
73  log->Printf("PlatformAppleTVSimulator::%s(force=%s, arch={%s,%s})",
74  __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
75  }
76 
77  bool create = force;
78  if (!create && arch && arch->IsValid()) {
79  switch (arch->GetMachine()) {
80  case llvm::Triple::x86_64: {
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::TvOS:
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  if (log)
124  log->Printf("PlatformAppleTVSimulator::%s() creating platform",
125  __FUNCTION__);
126 
127  return PlatformSP(new PlatformAppleTVSimulator());
128  }
129 
130  if (log)
131  log->Printf("PlatformAppleTVSimulator::%s() aborting creation of platform",
132  __FUNCTION__);
133 
134  return PlatformSP();
135 }
136 
138  static ConstString g_name("tvos-simulator");
139  return g_name;
140 }
141 
143  return "Apple TV simulator platform plug-in.";
144 }
145 
146 /// Default Constructor
148  : PlatformDarwin(true), m_sdk_dir_mutex(), m_sdk_directory() {}
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  const char *sdk_directory = GetSDKDirectoryAsCString();
159  if (sdk_directory)
160  strm.Printf(" SDK Path: \"%s\"\n", sdk_directory);
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 EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft,
243  llvm::StringRef path) {
244  if (ft == llvm::sys::fs::file_type::directory_file) {
245  FileSpec file_spec(path);
246  const char *filename = file_spec.GetFilename().GetCString();
247  if (filename &&
248  strncmp(filename, "AppleTVSimulator", strlen("AppleTVSimulator")) ==
249  0) {
250  ::snprintf((char *)baton, PATH_MAX, "%s", filename);
251  return FileSystem::eEnumerateDirectoryResultQuit;
252  }
253  }
254  return FileSystem::eEnumerateDirectoryResultNext;
255 }
256 
258  std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
259  if (m_sdk_directory.empty()) {
260  const char *developer_dir = GetDeveloperDirectory();
261  if (developer_dir) {
262  char sdks_directory[PATH_MAX];
263  char sdk_dirname[PATH_MAX];
264  sdk_dirname[0] = '\0';
265  snprintf(sdks_directory, sizeof(sdks_directory),
266  "%s/Platforms/AppleTVSimulator.platform/Developer/SDKs",
267  developer_dir);
268  FileSpec simulator_sdk_spec;
269  bool find_directories = true;
270  bool find_files = false;
271  bool find_other = false;
272  FileSystem::Instance().EnumerateDirectory(
273  sdks_directory, find_directories, find_files, find_other,
274  EnumerateDirectoryCallback, sdk_dirname);
275 
276  if (sdk_dirname[0]) {
277  m_sdk_directory = sdks_directory;
278  m_sdk_directory.append(1, '/');
279  m_sdk_directory.append(sdk_dirname);
280  return m_sdk_directory.c_str();
281  }
282  }
283  // Assign a single NULL character so we know we tried to find the device
284  // support directory and we don't keep trying to find it over and over.
285  m_sdk_directory.assign(1, '\0');
286  }
287 
288  // We should have put a single NULL character into m_sdk_directory or it
289  // should have a valid path if the code gets here
290  assert(m_sdk_directory.empty() == false);
291  if (m_sdk_directory[0])
292  return m_sdk_directory.c_str();
293  return NULL;
294 }
295 
297  const UUID *uuid_ptr,
298  FileSpec &local_file) {
299  Status error;
300  char platform_file_path[PATH_MAX];
301  if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
302  char resolved_path[PATH_MAX];
303 
304  const char *sdk_dir = GetSDKDirectoryAsCString();
305  if (sdk_dir) {
306  ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", sdk_dir,
307  platform_file_path);
308 
309  // First try in the SDK and see if the file is in there
310  local_file.SetFile(resolved_path, FileSpec::Style::native);
311  FileSystem::Instance().Resolve(local_file);
312  if (FileSystem::Instance().Exists(local_file))
313  return error;
314 
315  // Else fall back to the actual path itself
316  local_file.SetFile(platform_file_path, FileSpec::Style::native);
317  FileSystem::Instance().Resolve(local_file);
318  if (FileSystem::Instance().Exists(local_file))
319  return error;
320  }
322  "unable to locate a platform file for '%s' in platform '%s'",
323  platform_file_path, GetPluginName().GetCString());
324  } else {
325  error.SetErrorString("invalid platform file argument");
326  }
327  return error;
328 }
329 
331  const ModuleSpec &module_spec, lldb_private::Process *process,
332  ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr,
333  ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
334  // For AppleTV, the SDK files are all cached locally on the host system. So
335  // first we ask for the file in the cached SDK, then we attempt to get a
336  // shared module for the right architecture with the right UUID.
337  Status error;
338  ModuleSpec platform_module_spec(module_spec);
339  const FileSpec &platform_file = module_spec.GetFileSpec();
340  error = GetSymbolFile(platform_file, module_spec.GetUUIDPtr(),
341  platform_module_spec.GetFileSpec());
342  if (error.Success()) {
343  error = ResolveExecutable(platform_module_spec, module_sp,
344  module_search_paths_ptr);
345  } else {
346  const bool always_create = false;
347  error = ModuleList::GetSharedModule(
348  module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
349  did_create_ptr, always_create);
350  }
351  if (module_sp)
352  module_sp->SetPlatformFileSpec(platform_file);
353 
354  return error;
355 }
356 
358  const ProcessInstanceInfoMatch &match_info,
359  ProcessInstanceInfoList &process_infos) {
360  ProcessInstanceInfoList all_osx_process_infos;
361  // First we get all OSX processes
362  const uint32_t n = Host::FindProcesses(match_info, all_osx_process_infos);
363 
364  // Now we filter them down to only the TvOS triples
365  for (uint32_t i = 0; i < n; ++i) {
366  const ProcessInstanceInfo &proc_info =
367  all_osx_process_infos.GetProcessInfoAtIndex(i);
368  if (proc_info.GetArchitecture().GetTriple().getOS() == llvm::Triple::TvOS) {
369  process_infos.Append(proc_info);
370  }
371  }
372  return process_infos.GetSize();
373 }
374 
376  ArchSpec &arch) {
377  static const ArchSpec platform_arch(
378  HostInfo::GetArchitecture(HostInfo::eArchKind64));
379 
380  if (idx == 0) {
381  arch = platform_arch;
382  if (arch.IsValid()) {
383  arch.GetTriple().setOS(llvm::Triple::TvOS);
384  return true;
385  }
386  }
387  return false;
388 }
ConstString & GetFilename()
Filename string get accessor.
Definition: FileSpec.cpp:369
virtual lldb_private::Status GetSymbolFile(const lldb_private::FileSpec &platform_file, const lldb_private::UUID *uuid_ptr, lldb_private::FileSpec &local_file)
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
Core GetCore() const
Definition: ArchSpec.h:410
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
virtual ~PlatformAppleTVSimulator()
Destructor.
void Append(const ProcessInstanceInfo &info)
Definition: ProcessInfo.h:166
static const char * GetDescriptionStatic()
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
A file utility class.
Definition: FileSpec.h:55
An architecture specification class.
Definition: ArchSpec.h:32
lldb_private::ConstString GetPluginName() override
#define LIBLLDB_LOG_PLATFORM
Definition: Logging.h:39
static lldb_private::ConstString GetPluginNameStatic()
static void Terminate()
Definition: Platform.cpp:142
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:329
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:431
const char * GetDeveloperDirectory()
bool TripleVendorWasSpecified() const
Definition: ArchSpec.h:334
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:591
void SetErrorToGenericError()
Set the current error to a generic error.
Definition: Status.cpp:231
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
static void Initialize()
Definition: Platform.cpp:140
uint32_t FindProcesses(const lldb_private::ProcessInstanceInfoMatch &match_info, lldb_private::ProcessInstanceInfoList &process_infos) override
Attach to an existing process by process name.
const ProcessInstanceInfo & GetProcessInfoAtIndex(size_t idx) const
Definition: ProcessInfo.h:189
llvm::StringRef GetString() const
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
ArchSpec & GetArchitecture()
Definition: ProcessInfo.h:62
bool Success() const
Test for success condition.
Definition: Status.cpp:287
FileSpec & GetFileSpec()
Definition: ModuleSpec.h:75
static FileSystem::EnumerateDirectoryResult EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path)
PlatformAppleTVSimulator()
Default Constructor.
ArchSpec & GetArchitecture()
Definition: ModuleSpec.h:111
void GetStatus(lldb_private::Stream &strm) override
Report the current status for this platform.
A uniqued constant string class.
Definition: ConstString.h:38
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:247
static lldb::PlatformSP CreateInstance(bool force, const lldb_private::ArchSpec *arch)
Definition: SBAddress.h:15
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.
bool TripleOSWasSpecified() const
Definition: ArchSpec.h:338
lldb_private::Status ResolveExecutable(const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr) override
#define PATH_MAX
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:198
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:376
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:726
An error handling class.
Definition: Status.h:44
static uint32_t g_initialize_count