PlatformiOSSimulator.cpp revision b1db658333cdebca31a128be95e926d80c3c7796
1//===-- PlatformiOSSimulator.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 "PlatformiOSSimulator.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/Module.h"
20#include "lldb/Core/ModuleList.h"
21#include "lldb/Core/PluginManager.h"
22#include "lldb/Core/StreamString.h"
23#include "lldb/Host/FileSpec.h"
24#include "lldb/Host/Host.h"
25#include "lldb/Target/Process.h"
26#include "lldb/Target/Target.h"
27
28using namespace lldb;
29using namespace lldb_private;
30
31//------------------------------------------------------------------
32// Static Variables
33//------------------------------------------------------------------
34static uint32_t g_initialize_count = 0;
35
36//------------------------------------------------------------------
37// Static Functions
38//------------------------------------------------------------------
39void
40PlatformiOSSimulator::Initialize ()
41{
42    if (g_initialize_count++ == 0)
43    {
44        PluginManager::RegisterPlugin (PlatformiOSSimulator::GetShortPluginNameStatic(),
45                                       PlatformiOSSimulator::GetDescriptionStatic(),
46                                       PlatformiOSSimulator::CreateInstance);
47    }
48}
49
50void
51PlatformiOSSimulator::Terminate ()
52{
53    if (g_initialize_count > 0)
54    {
55        if (--g_initialize_count == 0)
56        {
57            PluginManager::UnregisterPlugin (PlatformiOSSimulator::CreateInstance);
58        }
59    }
60}
61
62Platform*
63PlatformiOSSimulator::CreateInstance (bool force, const ArchSpec *arch)
64{
65    bool create = force;
66    if (create == false && arch && arch->IsValid())
67    {
68        switch (arch->GetMachine())
69        {
70        // Currently simulator is i386 only...
71        case llvm::Triple::x86:
72            {
73                const llvm::Triple &triple = arch->GetTriple();
74                const llvm::Triple::OSType os = triple.getOS();
75                const llvm::Triple::VendorType vendor = triple.getVendor();
76                if (os == llvm::Triple::Darwin && vendor == llvm::Triple::Apple)
77                    create = true;
78            }
79            break;
80        default:
81            break;
82        }
83    }
84    if (create)
85        return new PlatformiOSSimulator ();
86    return NULL;
87}
88
89
90const char *
91PlatformiOSSimulator::GetPluginNameStatic ()
92{
93    return "PlatformiOSSimulator";
94}
95
96const char *
97PlatformiOSSimulator::GetShortPluginNameStatic()
98{
99    return "ios-simulator";
100}
101
102const char *
103PlatformiOSSimulator::GetDescriptionStatic()
104{
105    return "iOS simulator platform plug-in.";
106}
107
108
109//------------------------------------------------------------------
110/// Default Constructor
111//------------------------------------------------------------------
112PlatformiOSSimulator::PlatformiOSSimulator () :
113    PlatformDarwin (false),
114    m_sdk_directory ()
115{
116}
117
118//------------------------------------------------------------------
119/// Destructor.
120///
121/// The destructor is virtual since this class is designed to be
122/// inherited from by the plug-in instance.
123//------------------------------------------------------------------
124PlatformiOSSimulator::~PlatformiOSSimulator()
125{
126}
127
128
129void
130PlatformiOSSimulator::GetStatus (Stream &strm)
131{
132    Platform::GetStatus (strm);
133    const char *sdk_directory = GetSDKDirectory();
134    if (sdk_directory)
135        strm.Printf ("  SDK Path: \"%s\"\n", sdk_directory);
136    else
137        strm.PutCString ("  SDK Path: error: unable to locate SDK\n");
138}
139
140
141Error
142PlatformiOSSimulator::ResolveExecutable (const FileSpec &exe_file,
143                                         const ArchSpec &exe_arch,
144                                         lldb::ModuleSP &exe_module_sp,
145                                         const FileSpecList *module_search_paths_ptr)
146{
147    Error error;
148    // Nothing special to do here, just use the actual file and architecture
149
150    FileSpec resolved_exe_file (exe_file);
151
152    // If we have "ls" as the exe_file, resolve the executable loation based on
153    // the current path variables
154    // TODO: resolve bare executables in the Platform SDK
155//    if (!resolved_exe_file.Exists())
156//        resolved_exe_file.ResolveExecutableLocation ();
157
158    // Resolve any executable within a bundle on MacOSX
159    // TODO: verify that this handles shallow bundles, if not then implement one ourselves
160    Host::ResolveExecutableInBundle (resolved_exe_file);
161
162    if (resolved_exe_file.Exists())
163    {
164        ModuleSpec module_spec(resolved_exe_file, exe_arch);
165        if (exe_arch.IsValid())
166        {
167            error = ModuleList::GetSharedModule (module_spec,
168                                                 exe_module_sp,
169                                                 NULL,
170                                                 NULL,
171                                                 NULL);
172
173            if (exe_module_sp->GetObjectFile())
174                return error;
175            exe_module_sp.reset();
176        }
177        // No valid architecture was specified or the exact ARM slice wasn't
178        // found so ask the platform for the architectures that we should be
179        // using (in the correct order) and see if we can find a match that way
180        StreamString arch_names;
181        ArchSpec platform_arch;
182        for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
183        {
184
185            error = ModuleList::GetSharedModule (module_spec,
186                                                 exe_module_sp,
187                                                 NULL,
188                                                 NULL,
189                                                 NULL);
190            // Did we find an executable using one of the
191            if (error.Success())
192            {
193                if (exe_module_sp && exe_module_sp->GetObjectFile())
194                    break;
195                else
196                    error.SetErrorToGenericError();
197            }
198
199            if (idx > 0)
200                arch_names.PutCString (", ");
201            arch_names.PutCString (platform_arch.GetArchitectureName());
202        }
203
204        if (error.Fail() || !exe_module_sp)
205        {
206            error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
207                                            exe_file.GetDirectory().AsCString(""),
208                                            exe_file.GetDirectory() ? "/" : "",
209                                            exe_file.GetFilename().AsCString(""),
210                                            GetShortPluginName(),
211                                            arch_names.GetString().c_str());
212        }
213    }
214    else
215    {
216        error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
217                                        exe_file.GetDirectory().AsCString(""),
218                                        exe_file.GetDirectory() ? "/" : "",
219                                        exe_file.GetFilename().AsCString(""));
220    }
221
222    return error;
223}
224
225static FileSpec::EnumerateDirectoryResult
226EnumerateDirectoryCallback (void *baton, FileSpec::FileType file_type, const FileSpec &file_spec)
227{
228    if (file_type == FileSpec::eFileTypeDirectory)
229    {
230        const char *filename = file_spec.GetFilename().GetCString();
231        if (filename && strncmp(filename, "iPhoneSimulator", strlen ("iPhoneSimulator")) == 0)
232        {
233            ::snprintf ((char *)baton, PATH_MAX, "%s", filename);
234            return FileSpec::eEnumerateDirectoryResultQuit;
235        }
236    }
237    return FileSpec::eEnumerateDirectoryResultNext;
238}
239
240
241
242const char *
243PlatformiOSSimulator::GetSDKDirectory()
244{
245    if (m_sdk_directory.empty())
246    {
247        const char *developer_dir = GetDeveloperDirectory();
248        if (developer_dir)
249        {
250            char sdks_directory[PATH_MAX];
251            char sdk_dirname[PATH_MAX];
252            sdk_dirname[0] = '\0';
253            snprintf (sdks_directory,
254                      sizeof(sdks_directory),
255                      "%s/Platforms/iPhoneSimulator.platform/Developer/SDKs",
256                      developer_dir);
257            FileSpec simulator_sdk_spec;
258            bool find_directories = true;
259            bool find_files = false;
260            bool find_other = false;
261            FileSpec::EnumerateDirectory (sdks_directory,
262                                          find_directories,
263                                          find_files,
264                                          find_other,
265                                          EnumerateDirectoryCallback,
266                                          sdk_dirname);
267
268            if (sdk_dirname[0])
269            {
270                m_sdk_directory = sdks_directory;
271                m_sdk_directory.append (1, '/');
272                m_sdk_directory.append (sdk_dirname);
273                return m_sdk_directory.c_str();
274            }
275        }
276        // Assign a single NULL character so we know we tried to find the device
277        // support directory and we don't keep trying to find it over and over.
278        m_sdk_directory.assign (1, '\0');
279    }
280
281    // We should have put a single NULL character into m_sdk_directory
282    // or it should have a valid path if the code gets here
283    assert (m_sdk_directory.empty() == false);
284    if (m_sdk_directory[0])
285        return m_sdk_directory.c_str();
286    return NULL;
287}
288
289Error
290PlatformiOSSimulator::GetFile (const FileSpec &platform_file,
291                               const UUID *uuid_ptr,
292                               FileSpec &local_file)
293{
294    Error error;
295    char platform_file_path[PATH_MAX];
296    if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
297    {
298        char resolved_path[PATH_MAX];
299
300        const char * sdk_dir = GetSDKDirectory();
301        if (sdk_dir)
302        {
303            ::snprintf (resolved_path,
304                        sizeof(resolved_path),
305                        "%s/%s",
306                        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, true);
311            if (local_file.Exists())
312                return error;
313
314            // Else fall back to the actual path itself
315            local_file.SetFile(platform_file_path, true);
316            if (local_file.Exists())
317                return error;
318
319        }
320        error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
321                                        platform_file_path,
322                                        GetPluginName());
323    }
324    else
325    {
326        error.SetErrorString ("invalid platform file argument");
327    }
328    return error;
329}
330
331Error
332PlatformiOSSimulator::GetSharedModule (const ModuleSpec &module_spec,
333                                       ModuleSP &module_sp,
334                                       const FileSpecList *module_search_paths_ptr,
335                                       ModuleSP *old_module_sp_ptr,
336                                       bool *did_create_ptr)
337{
338    // For iOS, 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    FileSpec local_file;
344    const FileSpec &platform_file = module_spec.GetFileSpec();
345    error = GetFile (platform_file, module_spec.GetUUIDPtr(), local_file);
346    if (error.Success())
347    {
348        error = ResolveExecutable (local_file, module_spec.GetArchitecture(), module_sp, module_search_paths_ptr);
349    }
350    else
351    {
352        const bool always_create = false;
353        error = ModuleList::GetSharedModule (module_spec,
354                                             module_sp,
355                                             module_search_paths_ptr,
356                                             old_module_sp_ptr,
357                                             did_create_ptr,
358                                             always_create);
359
360    }
361    if (module_sp)
362        module_sp->SetPlatformFileSpec(platform_file);
363
364    return error;
365}
366
367
368uint32_t
369PlatformiOSSimulator::FindProcesses (const ProcessInstanceInfoMatch &match_info,
370                                     ProcessInstanceInfoList &process_infos)
371{
372    // TODO: if connected, send a packet to get the remote process infos by name
373    process_infos.Clear();
374    return 0;
375}
376
377bool
378PlatformiOSSimulator::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
379{
380    // TODO: if connected, send a packet to get the remote process info
381    process_info.Clear();
382    return false;
383}
384
385bool
386PlatformiOSSimulator::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
387{
388    if (idx == 0)
389    {
390        // All iOS simulator binaries are currently i386
391        arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
392        return arch.IsValid();
393    }
394    return false;
395}
396