1 //===-- RemoteAwarePlatform.cpp -------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Target/RemoteAwarePlatform.h" 10 #include "lldb/Core/Module.h" 11 #include "lldb/Core/ModuleList.h" 12 #include "lldb/Core/ModuleSpec.h" 13 #include "lldb/Host/FileCache.h" 14 #include "lldb/Host/FileSystem.h" 15 #include "lldb/Host/Host.h" 16 #include "lldb/Host/HostInfo.h" 17 #include "lldb/Utility/StreamString.h" 18 19 using namespace lldb_private; 20 using namespace lldb; 21 22 bool RemoteAwarePlatform::GetModuleSpec(const FileSpec &module_file_spec, 23 const ArchSpec &arch, 24 ModuleSpec &module_spec) { 25 if (m_remote_platform_sp) 26 return m_remote_platform_sp->GetModuleSpec(module_file_spec, arch, 27 module_spec); 28 29 return false; 30 } 31 32 Status RemoteAwarePlatform::ResolveExecutable( 33 const ModuleSpec &module_spec, ModuleSP &exe_module_sp, 34 const FileSpecList *module_search_paths_ptr) { 35 Status error; 36 // Nothing special to do here, just use the actual file and architecture 37 38 char exe_path[PATH_MAX]; 39 ModuleSpec resolved_module_spec(module_spec); 40 41 if (IsHost()) { 42 // If we have "ls" as the exe_file, resolve the executable location based 43 // on the current path variables 44 if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { 45 resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); 46 resolved_module_spec.GetFileSpec().SetFile(exe_path, 47 FileSpec::Style::native); 48 FileSystem::Instance().Resolve(resolved_module_spec.GetFileSpec()); 49 } 50 51 if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) 52 FileSystem::Instance().ResolveExecutableLocation( 53 resolved_module_spec.GetFileSpec()); 54 55 // Resolve any executable within a bundle on MacOSX 56 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); 57 58 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) 59 error.Clear(); 60 else { 61 const uint32_t permissions = FileSystem::Instance().GetPermissions( 62 resolved_module_spec.GetFileSpec()); 63 if (permissions && (permissions & eFilePermissionsEveryoneR) == 0) 64 error.SetErrorStringWithFormat( 65 "executable '%s' is not readable", 66 resolved_module_spec.GetFileSpec().GetPath().c_str()); 67 else 68 error.SetErrorStringWithFormat( 69 "unable to find executable for '%s'", 70 resolved_module_spec.GetFileSpec().GetPath().c_str()); 71 } 72 } else { 73 if (m_remote_platform_sp) { 74 return GetCachedExecutable(resolved_module_spec, exe_module_sp, 75 module_search_paths_ptr, 76 *m_remote_platform_sp); 77 } 78 79 // We may connect to a process and use the provided executable (Don't use 80 // local $PATH). 81 82 // Resolve any executable within a bundle on MacOSX 83 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); 84 85 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) 86 error.Clear(); 87 else 88 error.SetErrorStringWithFormat("the platform is not currently " 89 "connected, and '%s' doesn't exist in " 90 "the system root.", 91 exe_path); 92 } 93 94 if (error.Success()) { 95 if (resolved_module_spec.GetArchitecture().IsValid()) { 96 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 97 module_search_paths_ptr, nullptr, nullptr); 98 if (error.Fail()) { 99 // If we failed, it may be because the vendor and os aren't known. If 100 // that is the case, try setting them to the host architecture and give 101 // it another try. 102 llvm::Triple &module_triple = 103 resolved_module_spec.GetArchitecture().GetTriple(); 104 bool is_vendor_specified = 105 (module_triple.getVendor() != llvm::Triple::UnknownVendor); 106 bool is_os_specified = 107 (module_triple.getOS() != llvm::Triple::UnknownOS); 108 if (!is_vendor_specified || !is_os_specified) { 109 const llvm::Triple &host_triple = 110 HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple(); 111 112 if (!is_vendor_specified) 113 module_triple.setVendorName(host_triple.getVendorName()); 114 if (!is_os_specified) 115 module_triple.setOSName(host_triple.getOSName()); 116 117 error = ModuleList::GetSharedModule(resolved_module_spec, 118 exe_module_sp, module_search_paths_ptr, nullptr, nullptr); 119 } 120 } 121 122 // TODO find out why exe_module_sp might be NULL 123 if (error.Fail() || !exe_module_sp || !exe_module_sp->GetObjectFile()) { 124 exe_module_sp.reset(); 125 error.SetErrorStringWithFormat( 126 "'%s' doesn't contain the architecture %s", 127 resolved_module_spec.GetFileSpec().GetPath().c_str(), 128 resolved_module_spec.GetArchitecture().GetArchitectureName()); 129 } 130 } else { 131 // No valid architecture was specified, ask the platform for the 132 // architectures that we should be using (in the correct order) and see 133 // if we can find a match that way 134 StreamString arch_names; 135 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( 136 idx, resolved_module_spec.GetArchitecture()); 137 ++idx) { 138 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 139 module_search_paths_ptr, nullptr, nullptr); 140 // Did we find an executable using one of the 141 if (error.Success()) { 142 if (exe_module_sp && exe_module_sp->GetObjectFile()) 143 break; 144 else 145 error.SetErrorToGenericError(); 146 } 147 148 if (idx > 0) 149 arch_names.PutCString(", "); 150 arch_names.PutCString( 151 resolved_module_spec.GetArchitecture().GetArchitectureName()); 152 } 153 154 if (error.Fail() || !exe_module_sp) { 155 if (FileSystem::Instance().Readable( 156 resolved_module_spec.GetFileSpec())) { 157 error.SetErrorStringWithFormat( 158 "'%s' doesn't contain any '%s' platform architectures: %s", 159 resolved_module_spec.GetFileSpec().GetPath().c_str(), 160 GetPluginName().GetCString(), arch_names.GetData()); 161 } else { 162 error.SetErrorStringWithFormat( 163 "'%s' is not readable", 164 resolved_module_spec.GetFileSpec().GetPath().c_str()); 165 } 166 } 167 } 168 } 169 170 return error; 171 } 172 173 Status RemoteAwarePlatform::RunShellCommand( 174 llvm::StringRef command, const FileSpec &working_dir, int *status_ptr, 175 int *signo_ptr, std::string *command_output, 176 const Timeout<std::micro> &timeout) { 177 return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr, 178 signo_ptr, command_output, timeout); 179 } 180 181 Status RemoteAwarePlatform::RunShellCommand( 182 llvm::StringRef shell, llvm::StringRef command, const FileSpec &working_dir, 183 int *status_ptr, int *signo_ptr, std::string *command_output, 184 const Timeout<std::micro> &timeout) { 185 if (IsHost()) 186 return Host::RunShellCommand(shell, command, working_dir, status_ptr, 187 signo_ptr, command_output, timeout); 188 if (m_remote_platform_sp) 189 return m_remote_platform_sp->RunShellCommand(shell, command, working_dir, 190 status_ptr, signo_ptr, 191 command_output, timeout); 192 return Status("unable to run a remote command without a platform"); 193 } 194 195 Status RemoteAwarePlatform::MakeDirectory(const FileSpec &file_spec, 196 uint32_t file_permissions) { 197 if (m_remote_platform_sp) 198 return m_remote_platform_sp->MakeDirectory(file_spec, file_permissions); 199 return Platform::MakeDirectory(file_spec, file_permissions); 200 } 201 202 Status RemoteAwarePlatform::GetFilePermissions(const FileSpec &file_spec, 203 uint32_t &file_permissions) { 204 if (m_remote_platform_sp) 205 return m_remote_platform_sp->GetFilePermissions(file_spec, 206 file_permissions); 207 return Platform::GetFilePermissions(file_spec, file_permissions); 208 } 209 210 Status RemoteAwarePlatform::SetFilePermissions(const FileSpec &file_spec, 211 uint32_t file_permissions) { 212 if (m_remote_platform_sp) 213 return m_remote_platform_sp->SetFilePermissions(file_spec, 214 file_permissions); 215 return Platform::SetFilePermissions(file_spec, file_permissions); 216 } 217 218 lldb::user_id_t RemoteAwarePlatform::OpenFile(const FileSpec &file_spec, 219 File::OpenOptions flags, 220 uint32_t mode, Status &error) { 221 if (IsHost()) 222 return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error); 223 if (m_remote_platform_sp) 224 return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error); 225 return Platform::OpenFile(file_spec, flags, mode, error); 226 } 227 228 bool RemoteAwarePlatform::CloseFile(lldb::user_id_t fd, Status &error) { 229 if (IsHost()) 230 return FileCache::GetInstance().CloseFile(fd, error); 231 if (m_remote_platform_sp) 232 return m_remote_platform_sp->CloseFile(fd, error); 233 return Platform::CloseFile(fd, error); 234 } 235 236 uint64_t RemoteAwarePlatform::ReadFile(lldb::user_id_t fd, uint64_t offset, 237 void *dst, uint64_t dst_len, 238 Status &error) { 239 if (IsHost()) 240 return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error); 241 if (m_remote_platform_sp) 242 return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error); 243 return Platform::ReadFile(fd, offset, dst, dst_len, error); 244 } 245 246 uint64_t RemoteAwarePlatform::WriteFile(lldb::user_id_t fd, uint64_t offset, 247 const void *src, uint64_t src_len, 248 Status &error) { 249 if (IsHost()) 250 return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error); 251 if (m_remote_platform_sp) 252 return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error); 253 return Platform::WriteFile(fd, offset, src, src_len, error); 254 } 255 256 lldb::user_id_t RemoteAwarePlatform::GetFileSize(const FileSpec &file_spec) { 257 if (IsHost()) { 258 uint64_t Size; 259 if (llvm::sys::fs::file_size(file_spec.GetPath(), Size)) 260 return 0; 261 return Size; 262 } 263 if (m_remote_platform_sp) 264 return m_remote_platform_sp->GetFileSize(file_spec); 265 return Platform::GetFileSize(file_spec); 266 } 267 268 Status RemoteAwarePlatform::CreateSymlink(const FileSpec &src, 269 const FileSpec &dst) { 270 if (IsHost()) 271 return FileSystem::Instance().Symlink(src, dst); 272 if (m_remote_platform_sp) 273 return m_remote_platform_sp->CreateSymlink(src, dst); 274 return Platform::CreateSymlink(src, dst); 275 } 276 277 bool RemoteAwarePlatform::GetFileExists(const FileSpec &file_spec) { 278 if (IsHost()) 279 return FileSystem::Instance().Exists(file_spec); 280 if (m_remote_platform_sp) 281 return m_remote_platform_sp->GetFileExists(file_spec); 282 return Platform::GetFileExists(file_spec); 283 } 284 285 Status RemoteAwarePlatform::Unlink(const FileSpec &file_spec) { 286 if (IsHost()) 287 return llvm::sys::fs::remove(file_spec.GetPath()); 288 if (m_remote_platform_sp) 289 return m_remote_platform_sp->Unlink(file_spec); 290 return Platform::Unlink(file_spec); 291 } 292 293 bool RemoteAwarePlatform::CalculateMD5(const FileSpec &file_spec, uint64_t &low, 294 uint64_t &high) { 295 if (IsHost()) 296 return Platform::CalculateMD5(file_spec, low, high); 297 if (m_remote_platform_sp) 298 return m_remote_platform_sp->CalculateMD5(file_spec, low, high); 299 return false; 300 } 301 302 FileSpec RemoteAwarePlatform::GetRemoteWorkingDirectory() { 303 if (IsRemote() && m_remote_platform_sp) 304 return m_remote_platform_sp->GetRemoteWorkingDirectory(); 305 return Platform::GetRemoteWorkingDirectory(); 306 } 307 308 bool RemoteAwarePlatform::SetRemoteWorkingDirectory( 309 const FileSpec &working_dir) { 310 if (IsRemote() && m_remote_platform_sp) 311 return m_remote_platform_sp->SetRemoteWorkingDirectory(working_dir); 312 return Platform::SetRemoteWorkingDirectory(working_dir); 313 } 314 315 Status RemoteAwarePlatform::GetFileWithUUID(const FileSpec &platform_file, 316 const UUID *uuid_ptr, 317 FileSpec &local_file) { 318 if (IsRemote() && m_remote_platform_sp) 319 return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr, 320 local_file); 321 322 // Default to the local case 323 local_file = platform_file; 324 return Status(); 325 } 326 327 bool RemoteAwarePlatform::GetRemoteOSVersion() { 328 if (m_remote_platform_sp) { 329 m_os_version = m_remote_platform_sp->GetOSVersion(); 330 return !m_os_version.empty(); 331 } 332 return false; 333 } 334 335 bool RemoteAwarePlatform::GetRemoteOSBuildString(std::string &s) { 336 if (m_remote_platform_sp) 337 return m_remote_platform_sp->GetRemoteOSBuildString(s); 338 s.clear(); 339 return false; 340 } 341 342 bool RemoteAwarePlatform::GetRemoteOSKernelDescription(std::string &s) { 343 if (m_remote_platform_sp) 344 return m_remote_platform_sp->GetRemoteOSKernelDescription(s); 345 s.clear(); 346 return false; 347 } 348 349 ArchSpec RemoteAwarePlatform::GetRemoteSystemArchitecture() { 350 if (m_remote_platform_sp) 351 return m_remote_platform_sp->GetRemoteSystemArchitecture(); 352 return ArchSpec(); 353 } 354 355 const char *RemoteAwarePlatform::GetHostname() { 356 if (IsHost()) 357 return Platform::GetHostname(); 358 if (m_remote_platform_sp) 359 return m_remote_platform_sp->GetHostname(); 360 return nullptr; 361 } 362 363 UserIDResolver &RemoteAwarePlatform::GetUserIDResolver() { 364 if (IsHost()) 365 return HostInfo::GetUserIDResolver(); 366 if (m_remote_platform_sp) 367 return m_remote_platform_sp->GetUserIDResolver(); 368 return UserIDResolver::GetNoopResolver(); 369 } 370 371 Environment RemoteAwarePlatform::GetEnvironment() { 372 if (IsRemote()) { 373 if (m_remote_platform_sp) 374 return m_remote_platform_sp->GetEnvironment(); 375 return Environment(); 376 } 377 return Host::GetEnvironment(); 378 } 379 380 bool RemoteAwarePlatform::IsConnected() const { 381 if (IsHost()) 382 return true; 383 else if (m_remote_platform_sp) 384 return m_remote_platform_sp->IsConnected(); 385 return false; 386 } 387 388 bool RemoteAwarePlatform::GetProcessInfo(lldb::pid_t pid, 389 ProcessInstanceInfo &process_info) { 390 if (IsHost()) 391 return Platform::GetProcessInfo(pid, process_info); 392 if (m_remote_platform_sp) 393 return m_remote_platform_sp->GetProcessInfo(pid, process_info); 394 return false; 395 } 396 397 uint32_t 398 RemoteAwarePlatform::FindProcesses(const ProcessInstanceInfoMatch &match_info, 399 ProcessInstanceInfoList &process_infos) { 400 if (IsHost()) 401 return Platform::FindProcesses(match_info, process_infos); 402 if (m_remote_platform_sp) 403 return m_remote_platform_sp->FindProcesses(match_info, process_infos); 404 return 0; 405 } 406 407 lldb::ProcessSP RemoteAwarePlatform::ConnectProcess(llvm::StringRef connect_url, 408 llvm::StringRef plugin_name, 409 Debugger &debugger, 410 Target *target, 411 Status &error) { 412 if (m_remote_platform_sp) 413 return m_remote_platform_sp->ConnectProcess(connect_url, plugin_name, 414 debugger, target, error); 415 return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, 416 error); 417 } 418 419 Status RemoteAwarePlatform::LaunchProcess(ProcessLaunchInfo &launch_info) { 420 Status error; 421 422 if (IsHost()) { 423 error = Platform::LaunchProcess(launch_info); 424 } else { 425 if (m_remote_platform_sp) 426 error = m_remote_platform_sp->LaunchProcess(launch_info); 427 else 428 error.SetErrorString("the platform is not currently connected"); 429 } 430 return error; 431 } 432 433 Status RemoteAwarePlatform::KillProcess(const lldb::pid_t pid) { 434 if (IsHost()) 435 return Platform::KillProcess(pid); 436 if (m_remote_platform_sp) 437 return m_remote_platform_sp->KillProcess(pid); 438 return Status("the platform is not currently connected"); 439 } 440