1 //===-- PlatformRemoteiOS.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 "PlatformRemoteiOS.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 28 using namespace lldb; 29 using namespace lldb_private; 30 31 //------------------------------------------------------------------ 32 // Static Variables 33 //------------------------------------------------------------------ 34 static uint32_t g_initialize_count = 0; 35 36 //------------------------------------------------------------------ 37 // Static Functions 38 //------------------------------------------------------------------ 39 void 40 PlatformRemoteiOS::Initialize () 41 { 42 if (g_initialize_count++ == 0) 43 { 44 PluginManager::RegisterPlugin (PlatformRemoteiOS::GetShortPluginNameStatic(), 45 PlatformRemoteiOS::GetDescriptionStatic(), 46 PlatformRemoteiOS::CreateInstance); 47 } 48 } 49 50 void 51 PlatformRemoteiOS::Terminate () 52 { 53 if (g_initialize_count > 0) 54 { 55 if (--g_initialize_count == 0) 56 { 57 PluginManager::UnregisterPlugin (PlatformRemoteiOS::CreateInstance); 58 } 59 } 60 } 61 62 Platform* 63 PlatformRemoteiOS::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 case llvm::Triple::arm: 71 case llvm::Triple::thumb: 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 85 if (create) 86 return new PlatformRemoteiOS (); 87 return NULL; 88 } 89 90 91 const char * 92 PlatformRemoteiOS::GetPluginNameStatic () 93 { 94 return "PlatformRemoteiOS"; 95 } 96 97 const char * 98 PlatformRemoteiOS::GetShortPluginNameStatic() 99 { 100 return "remote-ios"; 101 } 102 103 const char * 104 PlatformRemoteiOS::GetDescriptionStatic() 105 { 106 return "Remote iOS platform plug-in."; 107 } 108 109 110 //------------------------------------------------------------------ 111 /// Default Constructor 112 //------------------------------------------------------------------ 113 PlatformRemoteiOS::PlatformRemoteiOS () : 114 PlatformDarwin (false), // This is a remote platform 115 m_device_support_directory_for_os_version () 116 { 117 } 118 119 //------------------------------------------------------------------ 120 /// Destructor. 121 /// 122 /// The destructor is virtual since this class is designed to be 123 /// inherited from by the plug-in instance. 124 //------------------------------------------------------------------ 125 PlatformRemoteiOS::~PlatformRemoteiOS() 126 { 127 } 128 129 130 void 131 PlatformRemoteiOS::GetStatus (Stream &strm) 132 { 133 Platform::GetStatus (strm); 134 const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion(); 135 if (sdk_directory) 136 strm.Printf (" SDK Path: \"%s\"\n", sdk_directory); 137 else 138 strm.PutCString (" SDK Path: error: unable to locate SDK\n"); 139 } 140 141 142 Error 143 PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file, 144 const ArchSpec &exe_arch, 145 lldb::ModuleSP &exe_module_sp, 146 const FileSpecList *module_search_paths_ptr) 147 { 148 Error error; 149 // Nothing special to do here, just use the actual file and architecture 150 151 FileSpec resolved_exe_file (exe_file); 152 153 // If we have "ls" as the exe_file, resolve the executable loation based on 154 // the current path variables 155 // TODO: resolve bare executables in the Platform SDK 156 // if (!resolved_exe_file.Exists()) 157 // resolved_exe_file.ResolveExecutableLocation (); 158 159 // Resolve any executable within a bundle on MacOSX 160 // TODO: verify that this handles shallow bundles, if not then implement one ourselves 161 Host::ResolveExecutableInBundle (resolved_exe_file); 162 163 if (resolved_exe_file.Exists()) 164 { 165 if (exe_arch.IsValid()) 166 { 167 ModuleSpec module_spec (resolved_exe_file, exe_arch); 168 error = ModuleList::GetSharedModule (module_spec, 169 exe_module_sp, 170 NULL, 171 NULL, 172 NULL); 173 174 if (exe_module_sp && exe_module_sp->GetObjectFile()) 175 return error; 176 exe_module_sp.reset(); 177 } 178 // No valid architecture was specified or the exact ARM slice wasn't 179 // found so ask the platform for the architectures that we should be 180 // using (in the correct order) and see if we can find a match that way 181 StreamString arch_names; 182 ArchSpec platform_arch; 183 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) 184 { 185 ModuleSpec module_spec (resolved_exe_file, platform_arch); 186 error = ModuleList::GetSharedModule (module_spec, 187 exe_module_sp, 188 NULL, 189 NULL, 190 NULL); 191 // Did we find an executable using one of the 192 if (error.Success()) 193 { 194 if (exe_module_sp && exe_module_sp->GetObjectFile()) 195 break; 196 else 197 error.SetErrorToGenericError(); 198 } 199 200 if (idx > 0) 201 arch_names.PutCString (", "); 202 arch_names.PutCString (platform_arch.GetArchitectureName()); 203 } 204 205 if (error.Fail() || !exe_module_sp) 206 { 207 error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s", 208 exe_file.GetDirectory().AsCString(""), 209 exe_file.GetDirectory() ? "/" : "", 210 exe_file.GetFilename().AsCString(""), 211 GetShortPluginName(), 212 arch_names.GetString().c_str()); 213 } 214 } 215 else 216 { 217 error.SetErrorStringWithFormat ("'%s%s%s' does not exist", 218 exe_file.GetDirectory().AsCString(""), 219 exe_file.GetDirectory() ? "/" : "", 220 exe_file.GetFilename().AsCString("")); 221 } 222 223 return error; 224 } 225 226 const char * 227 PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion() 228 { 229 if (m_sdk_sysroot) 230 return m_sdk_sysroot.GetCString(); 231 232 if (m_device_support_directory_for_os_version.empty()) 233 { 234 const char *device_support_dir = GetDeveloperDirectory(); 235 const bool resolve_path = true; 236 if (device_support_dir) 237 { 238 m_device_support_directory_for_os_version.assign (device_support_dir); 239 m_device_support_directory_for_os_version.append ("/Platforms/iPhoneOS.platform/DeviceSupport"); 240 241 uint32_t major = 0; 242 uint32_t minor = 0; 243 uint32_t update = 0; 244 FileSpec file_spec; 245 char resolved_path[PATH_MAX]; 246 if (GetOSVersion(major, minor, update)) 247 { 248 if (major != UINT32_MAX && minor != UINT32_MAX && update != UINT32_MAX) 249 { 250 ::snprintf (resolved_path, 251 sizeof(resolved_path), 252 "%s/%i.%i.%i", 253 m_device_support_directory_for_os_version.c_str(), 254 major, 255 minor, 256 update); 257 258 file_spec.SetFile(resolved_path, resolve_path); 259 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 260 { 261 m_device_support_directory_for_os_version.assign (resolved_path); 262 return m_device_support_directory_for_os_version.c_str(); 263 } 264 } 265 266 if (major != UINT32_MAX && minor != UINT32_MAX) 267 { 268 ::snprintf (resolved_path, 269 sizeof(resolved_path), 270 "%s/%i.%i", 271 m_device_support_directory_for_os_version.c_str(), 272 major, 273 minor); 274 275 file_spec.SetFile(resolved_path, resolve_path); 276 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 277 { 278 m_device_support_directory_for_os_version.assign (resolved_path); 279 return m_device_support_directory_for_os_version.c_str(); 280 } 281 } 282 } 283 else 284 { 285 // Use the default as we have no OS version selected 286 m_device_support_directory_for_os_version.append ("/Latest"); 287 file_spec.SetFile(m_device_support_directory_for_os_version.c_str(), resolve_path); 288 289 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 290 { 291 if (m_major_os_version == UINT32_MAX) 292 { 293 const char *resolved_latest_dirname = file_spec.GetFilename().GetCString(); 294 const char *pos = Args::StringToVersion (resolved_latest_dirname, 295 m_major_os_version, 296 m_minor_os_version, 297 m_update_os_version); 298 299 if (m_build_update.empty() && pos[0] == ' ' && pos[1] == '(') 300 { 301 const char *end_paren = strchr (pos + 2, ')'); 302 m_build_update.assign (pos + 2, end_paren); 303 } 304 } 305 m_device_support_directory_for_os_version.assign (resolved_path); 306 return m_device_support_directory_for_os_version.c_str(); 307 } 308 } 309 } 310 // Assign a single NULL character so we know we tried to find the device 311 // support directory and we don't keep trying to find it over and over. 312 m_device_support_directory_for_os_version.assign (1, '\0'); 313 } 314 // We should have put a single NULL character into m_device_support_directory_for_os_version 315 // or it should have a valid path if the code gets here 316 assert (m_device_support_directory_for_os_version.empty() == false); 317 if (m_device_support_directory_for_os_version[0]) 318 return m_device_support_directory_for_os_version.c_str(); 319 return NULL; 320 } 321 322 Error 323 PlatformRemoteiOS::GetFile (const FileSpec &platform_file, 324 const UUID *uuid_ptr, 325 FileSpec &local_file) 326 { 327 Error error; 328 char platform_file_path[PATH_MAX]; 329 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) 330 { 331 char resolved_path[PATH_MAX]; 332 333 const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion(); 334 if (os_version_dir) 335 { 336 ::snprintf (resolved_path, 337 sizeof(resolved_path), 338 "%s/%s", 339 os_version_dir, 340 platform_file_path); 341 342 local_file.SetFile(resolved_path, true); 343 if (local_file.Exists()) 344 return error; 345 346 ::snprintf (resolved_path, 347 sizeof(resolved_path), 348 "%s/Symbols.Internal/%s", 349 os_version_dir, 350 platform_file_path); 351 352 local_file.SetFile(resolved_path, true); 353 if (local_file.Exists()) 354 return error; 355 ::snprintf (resolved_path, 356 sizeof(resolved_path), 357 "%s/Symbols/%s", 358 os_version_dir, 359 platform_file_path); 360 361 local_file.SetFile(resolved_path, true); 362 if (local_file.Exists()) 363 return error; 364 365 } 366 local_file = platform_file; 367 if (local_file.Exists()) 368 return error; 369 370 error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", 371 platform_file_path, 372 GetPluginName()); 373 } 374 else 375 { 376 error.SetErrorString ("invalid platform file argument"); 377 } 378 return error; 379 } 380 381 Error 382 PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec, 383 ModuleSP &module_sp, 384 const FileSpecList *module_search_paths_ptr, 385 ModuleSP *old_module_sp_ptr, 386 bool *did_create_ptr) 387 { 388 // For iOS, the SDK files are all cached locally on the host 389 // system. So first we ask for the file in the cached SDK, 390 // then we attempt to get a shared module for the right architecture 391 // with the right UUID. 392 const FileSpec &platform_file = module_spec.GetFileSpec(); 393 394 FileSpec local_file; 395 Error error (GetFile (platform_file, module_spec.GetUUIDPtr(), local_file)); 396 if (error.Success()) 397 { 398 error = ResolveExecutable (local_file, module_spec.GetArchitecture(), module_sp, module_search_paths_ptr); 399 } 400 else 401 { 402 const bool always_create = false; 403 error = ModuleList::GetSharedModule (module_spec, 404 module_sp, 405 module_search_paths_ptr, 406 old_module_sp_ptr, 407 did_create_ptr, 408 always_create); 409 410 } 411 if (module_sp) 412 module_sp->SetPlatformFileSpec(platform_file); 413 414 return error; 415 } 416 417 418 uint32_t 419 PlatformRemoteiOS::FindProcesses (const ProcessInstanceInfoMatch &match_info, 420 ProcessInstanceInfoList &process_infos) 421 { 422 // TODO: if connected, send a packet to get the remote process infos by name 423 process_infos.Clear(); 424 return 0; 425 } 426 427 bool 428 PlatformRemoteiOS::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 429 { 430 // TODO: if connected, send a packet to get the remote process info 431 process_info.Clear(); 432 return false; 433 } 434 435 bool 436 PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 437 { 438 return ARMGetSupportedArchitectureAtIndex (idx, arch); 439 } 440