1 //===-- PlatformMacOSX.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 "PlatformMacOSX.h"
11 #include "lldb/Host/Config.h"
12 
13 // C Includes
14 #ifndef LLDB_DISABLE_POSIX
15 #include <sys/stat.h>
16 #include <sys/sysctl.h>
17 #endif
18 
19 // C++ Includes
20 
21 #include <sstream>
22 
23 // Other libraries and framework includes
24 // Project includes
25 #include "lldb/Core/Error.h"
26 #include "lldb/Breakpoint/BreakpointLocation.h"
27 #include "lldb/Core/DataBufferHeap.h"
28 #include "lldb/Core/Module.h"
29 #include "lldb/Core/ModuleList.h"
30 #include "lldb/Core/PluginManager.h"
31 #include "lldb/Core/StreamString.h"
32 #include "lldb/Host/FileSpec.h"
33 #include "lldb/Host/Host.h"
34 #include "lldb/Target/Process.h"
35 #include "lldb/Target/Target.h"
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 
40 static uint32_t g_initialize_count = 0;
41 
42 void
43 PlatformMacOSX::Initialize ()
44 {
45     if (g_initialize_count++ == 0)
46     {
47 #if defined (__APPLE__)
48         PlatformSP default_platform_sp (new PlatformMacOSX(true));
49         default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
50         Platform::SetDefaultPlatform (default_platform_sp);
51 #endif
52         PluginManager::RegisterPlugin (PlatformMacOSX::GetPluginNameStatic(false),
53                                        PlatformMacOSX::GetDescriptionStatic(false),
54                                        PlatformMacOSX::CreateInstance);
55     }
56 
57 }
58 
59 void
60 PlatformMacOSX::Terminate ()
61 {
62     if (g_initialize_count > 0)
63     {
64         if (--g_initialize_count == 0)
65         {
66             PluginManager::UnregisterPlugin (PlatformMacOSX::CreateInstance);
67         }
68     }
69 }
70 
71 Platform*
72 PlatformMacOSX::CreateInstance (bool force, const ArchSpec *arch)
73 {
74     // The only time we create an instance is when we are creating a remote
75     // macosx platform
76     const bool is_host = false;
77 
78     bool create = force;
79     if (create == false && arch && arch->IsValid())
80     {
81         const llvm::Triple &triple = arch->GetTriple();
82         switch (triple.getVendor())
83         {
84             case llvm::Triple::Apple:
85                 create = true;
86                 break;
87 
88 #if defined(__APPLE__)
89             // Only accept "unknown" for vendor if the host is Apple and
90             // it "unknown" wasn't specified (it was just returned becasue it
91             // was NOT specified)
92             case llvm::Triple::UnknownArch:
93                 create = !arch->TripleVendorWasSpecified();
94                 break;
95 #endif
96             default:
97                 break;
98         }
99 
100         if (create)
101         {
102             switch (triple.getOS())
103             {
104                 case llvm::Triple::Darwin:  // Deprecated, but still support Darwin for historical reasons
105                 case llvm::Triple::MacOSX:
106                     break;
107 #if defined(__APPLE__)
108                 // Only accept "vendor" for vendor if the host is Apple and
109                 // it "unknown" wasn't specified (it was just returned becasue 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     }
121     if (create)
122         return new PlatformMacOSX (is_host);
123     return NULL;
124 }
125 
126 lldb_private::ConstString
127 PlatformMacOSX::GetPluginNameStatic (bool is_host)
128 {
129     if (is_host)
130     {
131         static ConstString g_host_name(Platform::GetHostPlatformName ());
132         return g_host_name;
133     }
134     else
135     {
136         static ConstString g_remote_name("remote-macosx");
137         return g_remote_name;
138     }
139 }
140 
141 const char *
142 PlatformMacOSX::GetDescriptionStatic (bool is_host)
143 {
144     if (is_host)
145         return "Local Mac OS X user platform plug-in.";
146     else
147         return "Remote Mac OS X user platform plug-in.";
148 }
149 
150 //------------------------------------------------------------------
151 /// Default Constructor
152 //------------------------------------------------------------------
153 PlatformMacOSX::PlatformMacOSX (bool is_host) :
154     PlatformDarwin (is_host)
155 {
156 }
157 
158 //------------------------------------------------------------------
159 /// Destructor.
160 ///
161 /// The destructor is virtual since this class is designed to be
162 /// inherited from by the plug-in instance.
163 //------------------------------------------------------------------
164 PlatformMacOSX::~PlatformMacOSX()
165 {
166 }
167 
168 Error
169 PlatformMacOSX::GetSymbolFile (const FileSpec &platform_file,
170                                const UUID *uuid_ptr,
171                                FileSpec &local_file)
172 {
173     if (IsRemote())
174     {
175         if (m_remote_platform_sp)
176             return m_remote_platform_sp->GetFile (platform_file, uuid_ptr, local_file);
177     }
178 
179     // Default to the local case
180     local_file = platform_file;
181     return Error();
182 }
183 
184 lldb_private::Error
185 PlatformMacOSX::GetFile (const lldb_private::FileSpec &platform_file,
186                          const lldb_private::UUID *uuid_ptr,
187                          lldb_private::FileSpec &local_file)
188 {
189     if (IsRemote() && m_remote_platform_sp)
190     {
191         std::string local_os_build;
192         Host::GetOSBuildString(local_os_build);
193         std::string remote_os_build;
194         m_remote_platform_sp->GetOSBuildString(remote_os_build);
195         if (local_os_build.compare(remote_os_build) == 0)
196         {
197             // same OS version: the local file is good enough
198             local_file = platform_file;
199             return Error();
200         }
201         else
202         {
203             // try to find the file in the cache
204             std::string cache_path(GetLocalCacheDirectory());
205             std::string module_path (platform_file.GetPath());
206             cache_path.append(module_path);
207             FileSpec module_cache_spec(cache_path.c_str(),false);
208             if (module_cache_spec.Exists())
209             {
210                 local_file = module_cache_spec;
211                 return Error();
212             }
213             // bring in the remote module file
214             FileSpec module_cache_folder = module_cache_spec.CopyByRemovingLastPathComponent();
215             StreamString mkdir_folder_cmd;
216             // try to make the local directory first
217             mkdir_folder_cmd.Printf("mkdir -p %s/%s", module_cache_folder.GetDirectory().AsCString(), module_cache_folder.GetFilename().AsCString());
218             Host::RunShellCommand(mkdir_folder_cmd.GetData(),
219                                   NULL,
220                                   NULL,
221                                   NULL,
222                                   NULL,
223                                   60);
224             Error err = GetFile(platform_file, module_cache_spec);
225             if (err.Fail())
226                 return err;
227             if (module_cache_spec.Exists())
228             {
229                 local_file = module_cache_spec;
230                 return Error();
231             }
232             else
233                 return Error("unable to obtain valid module file");
234         }
235     }
236     local_file = platform_file;
237     return Error();
238 }
239 
240 bool
241 PlatformMacOSX::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
242 {
243 #if defined (__arm__)
244     return ARMGetSupportedArchitectureAtIndex (idx, arch);
245 #else
246     return x86GetSupportedArchitectureAtIndex (idx, arch);
247 #endif
248 }
249 
250 lldb_private::Error
251 PlatformMacOSX::GetSharedModule (const lldb_private::ModuleSpec &module_spec,
252                                  lldb::ModuleSP &module_sp,
253                                  const lldb_private::FileSpecList *module_search_paths_ptr,
254                                  lldb::ModuleSP *old_module_sp_ptr,
255                                  bool *did_create_ptr)
256 {
257     return GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
258 }
259