1 //===-- PlatformAppleTVSimulator.cpp ----------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "PlatformAppleTVSimulator.h"
14 // Other libraries and framework includes
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Core/ArchSpec.h"
18 #include "lldb/Core/Error.h"
19 #include "lldb/Core/Log.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/ModuleList.h"
22 #include "lldb/Core/ModuleSpec.h"
23 #include "lldb/Core/PluginManager.h"
24 #include "lldb/Core/StreamString.h"
25 #include "lldb/Host/FileSpec.h"
26 #include "lldb/Host/Host.h"
27 #include "lldb/Host/HostInfo.h"
28 #include "lldb/Target/Process.h"
29 #include "lldb/Target/Target.h"
32 using namespace lldb_private;
34 //------------------------------------------------------------------
36 //------------------------------------------------------------------
37 static uint32_t g_initialize_count = 0;
39 //------------------------------------------------------------------
41 //------------------------------------------------------------------
42 void PlatformAppleTVSimulator::Initialize() {
43 PlatformDarwin::Initialize();
45 if (g_initialize_count++ == 0) {
46 PluginManager::RegisterPlugin(
47 PlatformAppleTVSimulator::GetPluginNameStatic(),
48 PlatformAppleTVSimulator::GetDescriptionStatic(),
49 PlatformAppleTVSimulator::CreateInstance);
53 void PlatformAppleTVSimulator::Terminate() {
54 if (g_initialize_count > 0) {
55 if (--g_initialize_count == 0) {
56 PluginManager::UnregisterPlugin(PlatformAppleTVSimulator::CreateInstance);
60 PlatformDarwin::Terminate();
63 PlatformSP PlatformAppleTVSimulator::CreateInstance(bool force,
64 const ArchSpec *arch) {
65 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
67 const char *arch_name;
68 if (arch && arch->GetArchitectureName())
69 arch_name = arch->GetArchitectureName();
73 const char *triple_cstr =
74 arch ? arch->GetTriple().getTriple().c_str() : "<null>";
76 log->Printf("PlatformAppleTVSimulator::%s(force=%s, arch={%s,%s})",
77 __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
81 if (create == false && arch && arch->IsValid()) {
82 switch (arch->GetMachine()) {
83 case llvm::Triple::x86_64: {
84 const llvm::Triple &triple = arch->GetTriple();
85 switch (triple.getVendor()) {
86 case llvm::Triple::Apple:
90 #if defined(__APPLE__)
91 // Only accept "unknown" for the vendor if the host is Apple and
92 // it "unknown" wasn't specified (it was just returned because it
94 case llvm::Triple::UnknownArch:
95 create = !arch->TripleVendorWasSpecified();
103 switch (triple.getOS()) {
104 case llvm::Triple::TvOS:
107 #if defined(__APPLE__)
108 // Only accept "unknown" for the OS if the host is Apple and
109 // it "unknown" wasn't specified (it was just returned because it
110 // was NOT specified)
111 case llvm::Triple::UnknownOS:
112 create = !arch->TripleOSWasSpecified();
127 log->Printf("PlatformAppleTVSimulator::%s() creating platform",
130 return PlatformSP(new PlatformAppleTVSimulator());
134 log->Printf("PlatformAppleTVSimulator::%s() aborting creation of platform",
140 lldb_private::ConstString PlatformAppleTVSimulator::GetPluginNameStatic() {
141 static ConstString g_name("tvos-simulator");
145 const char *PlatformAppleTVSimulator::GetDescriptionStatic() {
146 return "Apple TV simulator platform plug-in.";
149 //------------------------------------------------------------------
150 /// Default Constructor
151 //------------------------------------------------------------------
152 PlatformAppleTVSimulator::PlatformAppleTVSimulator()
153 : PlatformDarwin(true), m_sdk_dir_mutex(), m_sdk_directory() {}
155 //------------------------------------------------------------------
158 /// The destructor is virtual since this class is designed to be
159 /// inherited from by the plug-in instance.
160 //------------------------------------------------------------------
161 PlatformAppleTVSimulator::~PlatformAppleTVSimulator() {}
163 void PlatformAppleTVSimulator::GetStatus(Stream &strm) {
164 Platform::GetStatus(strm);
165 const char *sdk_directory = GetSDKDirectoryAsCString();
167 strm.Printf(" SDK Path: \"%s\"\n", sdk_directory);
169 strm.PutCString(" SDK Path: error: unable to locate SDK\n");
172 Error PlatformAppleTVSimulator::ResolveExecutable(
173 const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
174 const FileSpecList *module_search_paths_ptr) {
176 // Nothing special to do here, just use the actual file and architecture
178 ModuleSpec resolved_module_spec(module_spec);
180 // If we have "ls" as the exe_file, resolve the executable loation based on
181 // the current path variables
182 // TODO: resolve bare executables in the Platform SDK
183 // if (!resolved_exe_file.Exists())
184 // resolved_exe_file.ResolveExecutableLocation ();
186 // Resolve any executable within a bundle on MacOSX
187 // TODO: verify that this handles shallow bundles, if not then implement one
189 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
191 if (resolved_module_spec.GetFileSpec().Exists()) {
192 if (resolved_module_spec.GetArchitecture().IsValid()) {
193 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
196 if (exe_module_sp && exe_module_sp->GetObjectFile())
198 exe_module_sp.reset();
200 // No valid architecture was specified or the exact ARM slice wasn't
201 // found so ask the platform for the architectures that we should be
202 // using (in the correct order) and see if we can find a match that way
203 StreamString arch_names;
204 ArchSpec platform_arch;
205 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
206 idx, resolved_module_spec.GetArchitecture());
208 // Only match x86 with x86 and x86_64 with x86_64...
209 if (!module_spec.GetArchitecture().IsValid() ||
210 module_spec.GetArchitecture().GetCore() ==
211 resolved_module_spec.GetArchitecture().GetCore()) {
212 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
214 // Did we find an executable using one of the
215 if (error.Success()) {
216 if (exe_module_sp && exe_module_sp->GetObjectFile())
219 error.SetErrorToGenericError();
223 arch_names.PutCString(", ");
224 arch_names.PutCString(platform_arch.GetArchitectureName());
228 if (error.Fail() || !exe_module_sp) {
229 if (resolved_module_spec.GetFileSpec().Readable()) {
230 error.SetErrorStringWithFormat(
231 "'%s' doesn't contain any '%s' platform architectures: %s",
232 resolved_module_spec.GetFileSpec().GetPath().c_str(),
233 GetPluginName().GetCString(), arch_names.GetString().str().c_str());
235 error.SetErrorStringWithFormat(
236 "'%s' is not readable",
237 resolved_module_spec.GetFileSpec().GetPath().c_str());
241 error.SetErrorStringWithFormat("'%s' does not exist",
242 module_spec.GetFileSpec().GetPath().c_str());
248 static FileSpec::EnumerateDirectoryResult
249 EnumerateDirectoryCallback(void *baton, FileSpec::FileType file_type,
250 const FileSpec &file_spec) {
251 if (file_type == FileSpec::eFileTypeDirectory) {
252 const char *filename = file_spec.GetFilename().GetCString();
254 strncmp(filename, "AppleTVSimulator", strlen("AppleTVSimulator")) ==
256 ::snprintf((char *)baton, PATH_MAX, "%s", filename);
257 return FileSpec::eEnumerateDirectoryResultQuit;
260 return FileSpec::eEnumerateDirectoryResultNext;
263 const char *PlatformAppleTVSimulator::GetSDKDirectoryAsCString() {
264 std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
265 if (m_sdk_directory.empty()) {
266 const char *developer_dir = GetDeveloperDirectory();
268 char sdks_directory[PATH_MAX];
269 char sdk_dirname[PATH_MAX];
270 sdk_dirname[0] = '\0';
271 snprintf(sdks_directory, sizeof(sdks_directory),
272 "%s/Platforms/AppleTVSimulator.platform/Developer/SDKs",
274 FileSpec simulator_sdk_spec;
275 bool find_directories = true;
276 bool find_files = false;
277 bool find_other = false;
278 FileSpec::EnumerateDirectory(sdks_directory, find_directories, find_files,
279 find_other, EnumerateDirectoryCallback,
282 if (sdk_dirname[0]) {
283 m_sdk_directory = sdks_directory;
284 m_sdk_directory.append(1, '/');
285 m_sdk_directory.append(sdk_dirname);
286 return m_sdk_directory.c_str();
289 // Assign a single NULL character so we know we tried to find the device
290 // support directory and we don't keep trying to find it over and over.
291 m_sdk_directory.assign(1, '\0');
294 // We should have put a single NULL character into m_sdk_directory
295 // or it should have a valid path if the code gets here
296 assert(m_sdk_directory.empty() == false);
297 if (m_sdk_directory[0])
298 return m_sdk_directory.c_str();
302 Error PlatformAppleTVSimulator::GetSymbolFile(const FileSpec &platform_file,
303 const UUID *uuid_ptr,
304 FileSpec &local_file) {
306 char platform_file_path[PATH_MAX];
307 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
308 char resolved_path[PATH_MAX];
310 const char *sdk_dir = GetSDKDirectoryAsCString();
312 ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", sdk_dir,
315 // First try in the SDK and see if the file is in there
316 local_file.SetFile(resolved_path, true);
317 if (local_file.Exists())
320 // Else fall back to the actual path itself
321 local_file.SetFile(platform_file_path, true);
322 if (local_file.Exists())
325 error.SetErrorStringWithFormat(
326 "unable to locate a platform file for '%s' in platform '%s'",
327 platform_file_path, GetPluginName().GetCString());
329 error.SetErrorString("invalid platform file argument");
334 Error PlatformAppleTVSimulator::GetSharedModule(
335 const ModuleSpec &module_spec, lldb_private::Process *process,
336 ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr,
337 ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
338 // For AppleTV, the SDK files are all cached locally on the host
339 // system. So first we ask for the file in the cached SDK,
340 // then we attempt to get a shared module for the right architecture
341 // with the right UUID.
343 ModuleSpec platform_module_spec(module_spec);
344 const FileSpec &platform_file = module_spec.GetFileSpec();
345 error = GetSymbolFile(platform_file, module_spec.GetUUIDPtr(),
346 platform_module_spec.GetFileSpec());
347 if (error.Success()) {
348 error = ResolveExecutable(platform_module_spec, module_sp,
349 module_search_paths_ptr);
351 const bool always_create = false;
352 error = ModuleList::GetSharedModule(
353 module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
354 did_create_ptr, always_create);
357 module_sp->SetPlatformFileSpec(platform_file);
362 uint32_t PlatformAppleTVSimulator::FindProcesses(
363 const ProcessInstanceInfoMatch &match_info,
364 ProcessInstanceInfoList &process_infos) {
365 ProcessInstanceInfoList all_osx_process_infos;
366 // First we get all OSX processes
367 const uint32_t n = Host::FindProcesses(match_info, all_osx_process_infos);
369 // Now we filter them down to only the TvOS triples
370 for (uint32_t i = 0; i < n; ++i) {
371 const ProcessInstanceInfo &proc_info =
372 all_osx_process_infos.GetProcessInfoAtIndex(i);
373 if (proc_info.GetArchitecture().GetTriple().getOS() == llvm::Triple::TvOS) {
374 process_infos.Append(proc_info);
377 return process_infos.GetSize();
380 bool PlatformAppleTVSimulator::GetSupportedArchitectureAtIndex(uint32_t idx,
382 static const ArchSpec platform_arch(
383 HostInfo::GetArchitecture(HostInfo::eArchKind64));
386 arch = platform_arch;
387 if (arch.IsValid()) {
388 arch.GetTriple().setOS(llvm::Triple::TvOS);