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 () 64 { 65 return new PlatformRemoteiOS (); 66 } 67 68 69 const char * 70 PlatformRemoteiOS::GetPluginNameStatic () 71 { 72 return "PlatformRemoteiOS"; 73 } 74 75 const char * 76 PlatformRemoteiOS::GetShortPluginNameStatic() 77 { 78 return "remote-ios"; 79 } 80 81 const char * 82 PlatformRemoteiOS::GetDescriptionStatic() 83 { 84 return "Remote iOS platform plug-in."; 85 } 86 87 88 //------------------------------------------------------------------ 89 /// Default Constructor 90 //------------------------------------------------------------------ 91 PlatformRemoteiOS::PlatformRemoteiOS () : 92 PlatformDarwin (false), // This is a remote platform 93 m_device_support_directory_for_os_version () 94 { 95 } 96 97 //------------------------------------------------------------------ 98 /// Destructor. 99 /// 100 /// The destructor is virtual since this class is designed to be 101 /// inherited from by the plug-in instance. 102 //------------------------------------------------------------------ 103 PlatformRemoteiOS::~PlatformRemoteiOS() 104 { 105 } 106 107 108 void 109 PlatformRemoteiOS::GetStatus (Stream &strm) 110 { 111 Platform::GetStatus (strm); 112 const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion(); 113 if (sdk_directory) 114 strm.Printf (" SDK Path: \"%s\"\n", sdk_directory); 115 else 116 strm.PutCString (" SDK Path: error: unable to locate SDK\n"); 117 } 118 119 120 Error 121 PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file, 122 const ArchSpec &exe_arch, 123 lldb::ModuleSP &exe_module_sp, 124 const FileSpecList *module_search_paths_ptr) 125 { 126 Error error; 127 // Nothing special to do here, just use the actual file and architecture 128 129 FileSpec resolved_exe_file (exe_file); 130 131 // If we have "ls" as the exe_file, resolve the executable loation based on 132 // the current path variables 133 // TODO: resolve bare executables in the Platform SDK 134 // if (!resolved_exe_file.Exists()) 135 // resolved_exe_file.ResolveExecutableLocation (); 136 137 // Resolve any executable within a bundle on MacOSX 138 // TODO: verify that this handles shallow bundles, if not then implement one ourselves 139 Host::ResolveExecutableInBundle (resolved_exe_file); 140 141 if (resolved_exe_file.Exists()) 142 { 143 if (exe_arch.IsValid()) 144 { 145 ModuleSpec module_spec (resolved_exe_file, exe_arch); 146 error = ModuleList::GetSharedModule (module_spec, 147 exe_module_sp, 148 NULL, 149 NULL, 150 NULL); 151 152 if (exe_module_sp && exe_module_sp->GetObjectFile()) 153 return error; 154 exe_module_sp.reset(); 155 } 156 // No valid architecture was specified or the exact ARM slice wasn't 157 // found so ask the platform for the architectures that we should be 158 // using (in the correct order) and see if we can find a match that way 159 StreamString arch_names; 160 ArchSpec platform_arch; 161 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) 162 { 163 ModuleSpec module_spec (resolved_exe_file, platform_arch); 164 error = ModuleList::GetSharedModule (module_spec, 165 exe_module_sp, 166 NULL, 167 NULL, 168 NULL); 169 // Did we find an executable using one of the 170 if (error.Success()) 171 { 172 if (exe_module_sp && exe_module_sp->GetObjectFile()) 173 break; 174 else 175 error.SetErrorToGenericError(); 176 } 177 178 if (idx > 0) 179 arch_names.PutCString (", "); 180 arch_names.PutCString (platform_arch.GetArchitectureName()); 181 } 182 183 if (error.Fail() || !exe_module_sp) 184 { 185 error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s", 186 exe_file.GetDirectory().AsCString(""), 187 exe_file.GetDirectory() ? "/" : "", 188 exe_file.GetFilename().AsCString(""), 189 GetShortPluginName(), 190 arch_names.GetString().c_str()); 191 } 192 } 193 else 194 { 195 error.SetErrorStringWithFormat ("'%s%s%s' does not exist", 196 exe_file.GetDirectory().AsCString(""), 197 exe_file.GetDirectory() ? "/" : "", 198 exe_file.GetFilename().AsCString("")); 199 } 200 201 return error; 202 } 203 204 const char * 205 PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion() 206 { 207 if (m_sdk_sysroot) 208 return m_sdk_sysroot.GetCString(); 209 210 if (m_device_support_directory_for_os_version.empty()) 211 { 212 const char *device_support_dir = GetDeveloperDirectory(); 213 const bool resolve_path = true; 214 if (device_support_dir) 215 { 216 m_device_support_directory_for_os_version.assign (device_support_dir); 217 m_device_support_directory_for_os_version.append ("/Platforms/iPhoneOS.platform/DeviceSupport"); 218 219 uint32_t major = 0; 220 uint32_t minor = 0; 221 uint32_t update = 0; 222 FileSpec file_spec; 223 char resolved_path[PATH_MAX]; 224 if (GetOSVersion(major, minor, update)) 225 { 226 if (major != UINT32_MAX && minor != UINT32_MAX && update != UINT32_MAX) 227 { 228 ::snprintf (resolved_path, 229 sizeof(resolved_path), 230 "%s/%i.%i.%i", 231 m_device_support_directory_for_os_version.c_str(), 232 major, 233 minor, 234 update); 235 236 file_spec.SetFile(resolved_path, resolve_path); 237 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 238 { 239 m_device_support_directory_for_os_version.assign (resolved_path); 240 return m_device_support_directory_for_os_version.c_str(); 241 } 242 } 243 244 if (major != UINT32_MAX && minor != UINT32_MAX) 245 { 246 ::snprintf (resolved_path, 247 sizeof(resolved_path), 248 "%s/%i.%i", 249 m_device_support_directory_for_os_version.c_str(), 250 major, 251 minor); 252 253 file_spec.SetFile(resolved_path, resolve_path); 254 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 255 { 256 m_device_support_directory_for_os_version.assign (resolved_path); 257 return m_device_support_directory_for_os_version.c_str(); 258 } 259 } 260 } 261 else 262 { 263 // Use the default as we have no OS version selected 264 m_device_support_directory_for_os_version.append ("/Latest"); 265 file_spec.SetFile(m_device_support_directory_for_os_version.c_str(), resolve_path); 266 267 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 268 { 269 if (m_major_os_version == UINT32_MAX) 270 { 271 const char *resolved_latest_dirname = file_spec.GetFilename().GetCString(); 272 const char *pos = Args::StringToVersion (resolved_latest_dirname, 273 m_major_os_version, 274 m_minor_os_version, 275 m_update_os_version); 276 277 if (m_build_update.empty() && pos[0] == ' ' && pos[1] == '(') 278 { 279 const char *end_paren = strchr (pos + 2, ')'); 280 m_build_update.assign (pos + 2, end_paren); 281 } 282 } 283 m_device_support_directory_for_os_version.assign (resolved_path); 284 return m_device_support_directory_for_os_version.c_str(); 285 } 286 } 287 } 288 // Assign a single NULL character so we know we tried to find the device 289 // support directory and we don't keep trying to find it over and over. 290 m_device_support_directory_for_os_version.assign (1, '\0'); 291 } 292 // We should have put a single NULL character into m_device_support_directory_for_os_version 293 // or it should have a valid path if the code gets here 294 assert (m_device_support_directory_for_os_version.empty() == false); 295 if (m_device_support_directory_for_os_version[0]) 296 return m_device_support_directory_for_os_version.c_str(); 297 return NULL; 298 } 299 300 Error 301 PlatformRemoteiOS::GetFile (const FileSpec &platform_file, 302 const UUID *uuid_ptr, 303 FileSpec &local_file) 304 { 305 Error error; 306 char platform_file_path[PATH_MAX]; 307 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) 308 { 309 char resolved_path[PATH_MAX]; 310 311 const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion(); 312 if (os_version_dir) 313 { 314 ::snprintf (resolved_path, 315 sizeof(resolved_path), 316 "%s/%s", 317 os_version_dir, 318 platform_file_path); 319 320 local_file.SetFile(resolved_path, true); 321 if (local_file.Exists()) 322 return error; 323 324 ::snprintf (resolved_path, 325 sizeof(resolved_path), 326 "%s/Symbols.Internal/%s", 327 os_version_dir, 328 platform_file_path); 329 330 local_file.SetFile(resolved_path, true); 331 if (local_file.Exists()) 332 return error; 333 ::snprintf (resolved_path, 334 sizeof(resolved_path), 335 "%s/Symbols/%s", 336 os_version_dir, 337 platform_file_path); 338 339 local_file.SetFile(resolved_path, true); 340 if (local_file.Exists()) 341 return error; 342 343 } 344 local_file = platform_file; 345 if (local_file.Exists()) 346 return error; 347 348 error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", 349 platform_file_path, 350 GetPluginName()); 351 } 352 else 353 { 354 error.SetErrorString ("invalid platform file argument"); 355 } 356 return error; 357 } 358 359 Error 360 PlatformRemoteiOS::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 const FileSpec &platform_file = module_spec.GetFileSpec(); 371 372 FileSpec local_file; 373 Error 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 PlatformRemoteiOS::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 PlatformRemoteiOS::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 407 { 408 // TODO: if connected, send a packet to get the remote process info 409 process_info.Clear(); 410 return false; 411 } 412 413 bool 414 PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 415 { 416 return ARMGetSupportedArchitectureAtIndex (idx, arch); 417 } 418