]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / source / Plugins / Platform / MacOSX / PlatformAppleTVSimulator.cpp
1 //===-- PlatformAppleTVSimulator.cpp ----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "PlatformAppleTVSimulator.h"
11
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project 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"
30
31 using namespace lldb;
32 using namespace lldb_private;
33
34 //------------------------------------------------------------------
35 // Static Variables
36 //------------------------------------------------------------------
37 static uint32_t g_initialize_count = 0;
38
39 //------------------------------------------------------------------
40 // Static Functions
41 //------------------------------------------------------------------
42 void PlatformAppleTVSimulator::Initialize() {
43   PlatformDarwin::Initialize();
44
45   if (g_initialize_count++ == 0) {
46     PluginManager::RegisterPlugin(
47         PlatformAppleTVSimulator::GetPluginNameStatic(),
48         PlatformAppleTVSimulator::GetDescriptionStatic(),
49         PlatformAppleTVSimulator::CreateInstance);
50   }
51 }
52
53 void PlatformAppleTVSimulator::Terminate() {
54   if (g_initialize_count > 0) {
55     if (--g_initialize_count == 0) {
56       PluginManager::UnregisterPlugin(PlatformAppleTVSimulator::CreateInstance);
57     }
58   }
59
60   PlatformDarwin::Terminate();
61 }
62
63 PlatformSP PlatformAppleTVSimulator::CreateInstance(bool force,
64                                                     const ArchSpec *arch) {
65   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
66   if (log) {
67     const char *arch_name;
68     if (arch && arch->GetArchitectureName())
69       arch_name = arch->GetArchitectureName();
70     else
71       arch_name = "<null>";
72
73     const char *triple_cstr =
74         arch ? arch->GetTriple().getTriple().c_str() : "<null>";
75
76     log->Printf("PlatformAppleTVSimulator::%s(force=%s, arch={%s,%s})",
77                 __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
78   }
79
80   bool create = force;
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:
87         create = true;
88         break;
89
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
93       // was NOT specified)
94       case llvm::Triple::UnknownArch:
95         create = !arch->TripleVendorWasSpecified();
96         break;
97 #endif
98       default:
99         break;
100       }
101
102       if (create) {
103         switch (triple.getOS()) {
104         case llvm::Triple::TvOS:
105           break;
106
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();
113           break;
114 #endif
115         default:
116           create = false;
117           break;
118         }
119       }
120     } break;
121     default:
122       break;
123     }
124   }
125   if (create) {
126     if (log)
127       log->Printf("PlatformAppleTVSimulator::%s() creating platform",
128                   __FUNCTION__);
129
130     return PlatformSP(new PlatformAppleTVSimulator());
131   }
132
133   if (log)
134     log->Printf("PlatformAppleTVSimulator::%s() aborting creation of platform",
135                 __FUNCTION__);
136
137   return PlatformSP();
138 }
139
140 lldb_private::ConstString PlatformAppleTVSimulator::GetPluginNameStatic() {
141   static ConstString g_name("tvos-simulator");
142   return g_name;
143 }
144
145 const char *PlatformAppleTVSimulator::GetDescriptionStatic() {
146   return "Apple TV simulator platform plug-in.";
147 }
148
149 //------------------------------------------------------------------
150 /// Default Constructor
151 //------------------------------------------------------------------
152 PlatformAppleTVSimulator::PlatformAppleTVSimulator()
153     : PlatformDarwin(true), m_sdk_dir_mutex(), m_sdk_directory() {}
154
155 //------------------------------------------------------------------
156 /// Destructor.
157 ///
158 /// The destructor is virtual since this class is designed to be
159 /// inherited from by the plug-in instance.
160 //------------------------------------------------------------------
161 PlatformAppleTVSimulator::~PlatformAppleTVSimulator() {}
162
163 void PlatformAppleTVSimulator::GetStatus(Stream &strm) {
164   Platform::GetStatus(strm);
165   const char *sdk_directory = GetSDKDirectoryAsCString();
166   if (sdk_directory)
167     strm.Printf("  SDK Path: \"%s\"\n", sdk_directory);
168   else
169     strm.PutCString("  SDK Path: error: unable to locate SDK\n");
170 }
171
172 Error PlatformAppleTVSimulator::ResolveExecutable(
173     const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
174     const FileSpecList *module_search_paths_ptr) {
175   Error error;
176   // Nothing special to do here, just use the actual file and architecture
177
178   ModuleSpec resolved_module_spec(module_spec);
179
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 ();
185
186   // Resolve any executable within a bundle on MacOSX
187   // TODO: verify that this handles shallow bundles, if not then implement one
188   // ourselves
189   Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
190
191   if (resolved_module_spec.GetFileSpec().Exists()) {
192     if (resolved_module_spec.GetArchitecture().IsValid()) {
193       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
194                                           NULL, NULL, NULL);
195
196       if (exe_module_sp && exe_module_sp->GetObjectFile())
197         return error;
198       exe_module_sp.reset();
199     }
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());
207          ++idx) {
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,
213                                             NULL, NULL, NULL);
214         // Did we find an executable using one of the
215         if (error.Success()) {
216           if (exe_module_sp && exe_module_sp->GetObjectFile())
217             break;
218           else
219             error.SetErrorToGenericError();
220         }
221
222         if (idx > 0)
223           arch_names.PutCString(", ");
224         arch_names.PutCString(platform_arch.GetArchitectureName());
225       }
226     }
227
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());
234       } else {
235         error.SetErrorStringWithFormat(
236             "'%s' is not readable",
237             resolved_module_spec.GetFileSpec().GetPath().c_str());
238       }
239     }
240   } else {
241     error.SetErrorStringWithFormat("'%s' does not exist",
242                                    module_spec.GetFileSpec().GetPath().c_str());
243   }
244
245   return error;
246 }
247
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();
253     if (filename &&
254         strncmp(filename, "AppleTVSimulator", strlen("AppleTVSimulator")) ==
255             0) {
256       ::snprintf((char *)baton, PATH_MAX, "%s", filename);
257       return FileSpec::eEnumerateDirectoryResultQuit;
258     }
259   }
260   return FileSpec::eEnumerateDirectoryResultNext;
261 }
262
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();
267     if (developer_dir) {
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",
273                developer_dir);
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,
280                                    sdk_dirname);
281
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();
287       }
288     }
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');
292   }
293
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();
299   return NULL;
300 }
301
302 Error PlatformAppleTVSimulator::GetSymbolFile(const FileSpec &platform_file,
303                                               const UUID *uuid_ptr,
304                                               FileSpec &local_file) {
305   Error error;
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];
309
310     const char *sdk_dir = GetSDKDirectoryAsCString();
311     if (sdk_dir) {
312       ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", sdk_dir,
313                  platform_file_path);
314
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())
318         return error;
319
320       // Else fall back to the actual path itself
321       local_file.SetFile(platform_file_path, true);
322       if (local_file.Exists())
323         return error;
324     }
325     error.SetErrorStringWithFormat(
326         "unable to locate a platform file for '%s' in platform '%s'",
327         platform_file_path, GetPluginName().GetCString());
328   } else {
329     error.SetErrorString("invalid platform file argument");
330   }
331   return error;
332 }
333
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.
342   Error error;
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);
350   } else {
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);
355   }
356   if (module_sp)
357     module_sp->SetPlatformFileSpec(platform_file);
358
359   return error;
360 }
361
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);
368
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);
375     }
376   }
377   return process_infos.GetSize();
378 }
379
380 bool PlatformAppleTVSimulator::GetSupportedArchitectureAtIndex(uint32_t idx,
381                                                                ArchSpec &arch) {
382   static const ArchSpec platform_arch(
383       HostInfo::GetArchitecture(HostInfo::eArchKind64));
384
385   if (idx == 0) {
386     arch = platform_arch;
387     if (arch.IsValid()) {
388       arch.GetTriple().setOS(llvm::Triple::TvOS);
389       return true;
390     }
391   }
392   return false;
393 }