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 29 using namespace lldb; 30 using namespace lldb_private; 31 32 //------------------------------------------------------------------ 33 // Static Variables 34 //------------------------------------------------------------------ 35 static uint32_t g_initialize_count = 0; 36 37 //------------------------------------------------------------------ 38 // Static Functions 39 //------------------------------------------------------------------ 40 void 41 PlatformiOSSimulator::Initialize () 42 { 43 if (g_initialize_count++ == 0) 44 { 45 PluginManager::RegisterPlugin (PlatformiOSSimulator::GetPluginNameStatic(), 46 PlatformiOSSimulator::GetDescriptionStatic(), 47 PlatformiOSSimulator::CreateInstance); 48 } 49 } 50 51 void 52 PlatformiOSSimulator::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 63 Platform* 64 PlatformiOSSimulator::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 127 lldb_private::ConstString 128 PlatformiOSSimulator::GetPluginNameStatic () 129 { 130 static ConstString g_name("ios-simulator"); 131 return g_name; 132 } 133 134 const char * 135 PlatformiOSSimulator::GetDescriptionStatic() 136 { 137 return "iOS simulator platform plug-in."; 138 } 139 140 141 //------------------------------------------------------------------ 142 /// Default Constructor 143 //------------------------------------------------------------------ 144 PlatformiOSSimulator::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 //------------------------------------------------------------------ 156 PlatformiOSSimulator::~PlatformiOSSimulator() 157 { 158 } 159 160 161 void 162 PlatformiOSSimulator::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 173 Error 174 PlatformiOSSimulator::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 253 static FileSpec::EnumerateDirectoryResult 254 EnumerateDirectoryCallback (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 270 const char * 271 PlatformiOSSimulator::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 317 Error 318 PlatformiOSSimulator::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 359 Error 360 PlatformiOSSimulator::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 396 uint32_t 397 PlatformiOSSimulator::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 405 bool 406 PlatformiOSSimulator::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