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