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 } 77 78 // We may connect to a process and use the provided executable (Don't use 79 // local $PATH). 80 81 // Resolve any executable within a bundle on MacOSX 82 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); 83 84 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) 85 error.Clear(); 86 else 87 error.SetErrorStringWithFormat("the platform is not currently " 88 "connected, and '%s' doesn't exist in " 89 "the system root.", 90 exe_path); 91 } 92 93 if (error.Success()) { 94 if (resolved_module_spec.GetArchitecture().IsValid()) { 95 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 96 module_search_paths_ptr, nullptr, nullptr); 97 if (error.Fail()) { 98 // If we failed, it may be because the vendor and os aren't known. If 99 // that is the case, try setting them to the host architecture and give 100 // it another try. 101 llvm::Triple &module_triple = 102 resolved_module_spec.GetArchitecture().GetTriple(); 103 bool is_vendor_specified = 104 (module_triple.getVendor() != llvm::Triple::UnknownVendor); 105 bool is_os_specified = 106 (module_triple.getOS() != llvm::Triple::UnknownOS); 107 if (!is_vendor_specified || !is_os_specified) { 108 const llvm::Triple &host_triple = 109 HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple(); 110 111 if (!is_vendor_specified) 112 module_triple.setVendorName(host_triple.getVendorName()); 113 if (!is_os_specified) 114 module_triple.setOSName(host_triple.getOSName()); 115 116 error = ModuleList::GetSharedModule(resolved_module_spec, 117 exe_module_sp, module_search_paths_ptr, nullptr, nullptr); 118 } 119 } 120 121 // TODO find out why exe_module_sp might be NULL 122 if (error.Fail() || !exe_module_sp || !exe_module_sp->GetObjectFile()) { 123 exe_module_sp.reset(); 124 error.SetErrorStringWithFormat( 125 "'%s' doesn't contain the architecture %s", 126 resolved_module_spec.GetFileSpec().GetPath().c_str(), 127 resolved_module_spec.GetArchitecture().GetArchitectureName()); 128 } 129 } else { 130 // No valid architecture was specified, ask the platform for the 131 // architectures that we should be using (in the correct order) and see 132 // if we can find a match that way 133 StreamString arch_names; 134 llvm::ListSeparator LS; 135 ArchSpec process_host_arch; 136 for (const ArchSpec &arch : 137 GetSupportedArchitectures(process_host_arch)) { 138 resolved_module_spec.GetArchitecture() = arch; 139 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 140 module_search_paths_ptr, nullptr, nullptr); 141 // Did we find an executable using one of the 142 if (error.Success()) { 143 if (exe_module_sp && exe_module_sp->GetObjectFile()) 144 break; 145 else 146 error.SetErrorToGenericError(); 147 } 148 149 arch_names << LS << arch.GetArchitectureName(); 150 } 151 152 if (error.Fail() || !exe_module_sp) { 153 if (FileSystem::Instance().Readable( 154 resolved_module_spec.GetFileSpec())) { 155 error.SetErrorStringWithFormatv( 156 "'{0}' doesn't contain any '{1}' platform architectures: {2}", 157 resolved_module_spec.GetFileSpec(), GetPluginName(), 158 arch_names.GetData()); 159 } else { 160 error.SetErrorStringWithFormat( 161 "'%s' is not readable", 162 resolved_module_spec.GetFileSpec().GetPath().c_str()); 163 } 164 } 165 } 166 } 167 168 return error; 169 } 170 171 Status RemoteAwarePlatform::RunShellCommand( 172 llvm::StringRef command, const FileSpec &working_dir, int *status_ptr, 173 int *signo_ptr, std::string *command_output, 174 const Timeout<std::micro> &timeout) { 175 return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr, 176 signo_ptr, command_output, timeout); 177 } 178 179 Status RemoteAwarePlatform::RunShellCommand( 180 llvm::StringRef shell, llvm::StringRef command, const FileSpec &working_dir, 181 int *status_ptr, int *signo_ptr, std::string *command_output, 182 const Timeout<std::micro> &timeout) { 183 if (IsHost()) 184 return Host::RunShellCommand(shell, command, working_dir, status_ptr, 185 signo_ptr, command_output, timeout); 186 if (m_remote_platform_sp) 187 return m_remote_platform_sp->RunShellCommand(shell, command, working_dir, 188 status_ptr, signo_ptr, 189 command_output, timeout); 190 return Status("unable to run a remote command without a platform"); 191 } 192 193 Status RemoteAwarePlatform::MakeDirectory(const FileSpec &file_spec, 194 uint32_t file_permissions) { 195 if (m_remote_platform_sp) 196 return m_remote_platform_sp->MakeDirectory(file_spec, file_permissions); 197 return Platform::MakeDirectory(file_spec, file_permissions); 198 } 199 200 Status RemoteAwarePlatform::GetFilePermissions(const FileSpec &file_spec, 201 uint32_t &file_permissions) { 202 if (m_remote_platform_sp) 203 return m_remote_platform_sp->GetFilePermissions(file_spec, 204 file_permissions); 205 return Platform::GetFilePermissions(file_spec, file_permissions); 206 } 207 208 Status RemoteAwarePlatform::SetFilePermissions(const FileSpec &file_spec, 209 uint32_t file_permissions) { 210 if (m_remote_platform_sp) 211 return m_remote_platform_sp->SetFilePermissions(file_spec, 212 file_permissions); 213 return Platform::SetFilePermissions(file_spec, file_permissions); 214 } 215 216 lldb::user_id_t RemoteAwarePlatform::OpenFile(const FileSpec &file_spec, 217 File::OpenOptions flags, 218 uint32_t mode, Status &error) { 219 if (IsHost()) 220 return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error); 221 if (m_remote_platform_sp) 222 return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error); 223 return Platform::OpenFile(file_spec, flags, mode, error); 224 } 225 226 bool RemoteAwarePlatform::CloseFile(lldb::user_id_t fd, Status &error) { 227 if (IsHost()) 228 return FileCache::GetInstance().CloseFile(fd, error); 229 if (m_remote_platform_sp) 230 return m_remote_platform_sp->CloseFile(fd, error); 231 return Platform::CloseFile(fd, error); 232 } 233 234 uint64_t RemoteAwarePlatform::ReadFile(lldb::user_id_t fd, uint64_t offset, 235 void *dst, uint64_t dst_len, 236 Status &error) { 237 if (IsHost()) 238 return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error); 239 if (m_remote_platform_sp) 240 return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error); 241 return Platform::ReadFile(fd, offset, dst, dst_len, error); 242 } 243 244 uint64_t RemoteAwarePlatform::WriteFile(lldb::user_id_t fd, uint64_t offset, 245 const void *src, uint64_t src_len, 246 Status &error) { 247 if (IsHost()) 248 return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error); 249 if (m_remote_platform_sp) 250 return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error); 251 return Platform::WriteFile(fd, offset, src, src_len, error); 252 } 253 254 lldb::user_id_t RemoteAwarePlatform::GetFileSize(const FileSpec &file_spec) { 255 if (IsHost()) { 256 uint64_t Size; 257 if (llvm::sys::fs::file_size(file_spec.GetPath(), Size)) 258 return 0; 259 return Size; 260 } 261 if (m_remote_platform_sp) 262 return m_remote_platform_sp->GetFileSize(file_spec); 263 return Platform::GetFileSize(file_spec); 264 } 265 266 Status RemoteAwarePlatform::CreateSymlink(const FileSpec &src, 267 const FileSpec &dst) { 268 if (IsHost()) 269 return FileSystem::Instance().Symlink(src, dst); 270 if (m_remote_platform_sp) 271 return m_remote_platform_sp->CreateSymlink(src, dst); 272 return Platform::CreateSymlink(src, dst); 273 } 274 275 bool RemoteAwarePlatform::GetFileExists(const FileSpec &file_spec) { 276 if (IsHost()) 277 return FileSystem::Instance().Exists(file_spec); 278 if (m_remote_platform_sp) 279 return m_remote_platform_sp->GetFileExists(file_spec); 280 return Platform::GetFileExists(file_spec); 281 } 282 283 Status RemoteAwarePlatform::Unlink(const FileSpec &file_spec) { 284 if (IsHost()) 285 return llvm::sys::fs::remove(file_spec.GetPath()); 286 if (m_remote_platform_sp) 287 return m_remote_platform_sp->Unlink(file_spec); 288 return Platform::Unlink(file_spec); 289 } 290 291 bool RemoteAwarePlatform::CalculateMD5(const FileSpec &file_spec, uint64_t &low, 292 uint64_t &high) { 293 if (IsHost()) 294 return Platform::CalculateMD5(file_spec, low, high); 295 if (m_remote_platform_sp) 296 return m_remote_platform_sp->CalculateMD5(file_spec, low, high); 297 return false; 298 } 299 300 FileSpec RemoteAwarePlatform::GetRemoteWorkingDirectory() { 301 if (IsRemote() && m_remote_platform_sp) 302 return m_remote_platform_sp->GetRemoteWorkingDirectory(); 303 return Platform::GetRemoteWorkingDirectory(); 304 } 305 306 bool RemoteAwarePlatform::SetRemoteWorkingDirectory( 307 const FileSpec &working_dir) { 308 if (IsRemote() && m_remote_platform_sp) 309 return m_remote_platform_sp->SetRemoteWorkingDirectory(working_dir); 310 return Platform::SetRemoteWorkingDirectory(working_dir); 311 } 312 313 Status RemoteAwarePlatform::GetFileWithUUID(const FileSpec &platform_file, 314 const UUID *uuid_ptr, 315 FileSpec &local_file) { 316 if (IsRemote() && m_remote_platform_sp) 317 return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr, 318 local_file); 319 320 // Default to the local case 321 local_file = platform_file; 322 return Status(); 323 } 324 325 bool RemoteAwarePlatform::GetRemoteOSVersion() { 326 if (m_remote_platform_sp) { 327 m_os_version = m_remote_platform_sp->GetOSVersion(); 328 return !m_os_version.empty(); 329 } 330 return false; 331 } 332 333 llvm::Optional<std::string> RemoteAwarePlatform::GetRemoteOSBuildString() { 334 if (m_remote_platform_sp) 335 return m_remote_platform_sp->GetRemoteOSBuildString(); 336 return llvm::None; 337 } 338 339 llvm::Optional<std::string> RemoteAwarePlatform::GetRemoteOSKernelDescription() { 340 if (m_remote_platform_sp) 341 return m_remote_platform_sp->GetRemoteOSKernelDescription(); 342 return llvm::None; 343 } 344 345 ArchSpec RemoteAwarePlatform::GetRemoteSystemArchitecture() { 346 if (m_remote_platform_sp) 347 return m_remote_platform_sp->GetRemoteSystemArchitecture(); 348 return ArchSpec(); 349 } 350 351 const char *RemoteAwarePlatform::GetHostname() { 352 if (IsHost()) 353 return Platform::GetHostname(); 354 if (m_remote_platform_sp) 355 return m_remote_platform_sp->GetHostname(); 356 return nullptr; 357 } 358 359 UserIDResolver &RemoteAwarePlatform::GetUserIDResolver() { 360 if (IsHost()) 361 return HostInfo::GetUserIDResolver(); 362 if (m_remote_platform_sp) 363 return m_remote_platform_sp->GetUserIDResolver(); 364 return UserIDResolver::GetNoopResolver(); 365 } 366 367 Environment RemoteAwarePlatform::GetEnvironment() { 368 if (IsRemote()) { 369 if (m_remote_platform_sp) 370 return m_remote_platform_sp->GetEnvironment(); 371 return Environment(); 372 } 373 return Host::GetEnvironment(); 374 } 375 376 bool RemoteAwarePlatform::IsConnected() const { 377 if (IsHost()) 378 return true; 379 else if (m_remote_platform_sp) 380 return m_remote_platform_sp->IsConnected(); 381 return false; 382 } 383 384 bool RemoteAwarePlatform::GetProcessInfo(lldb::pid_t pid, 385 ProcessInstanceInfo &process_info) { 386 if (IsHost()) 387 return Platform::GetProcessInfo(pid, process_info); 388 if (m_remote_platform_sp) 389 return m_remote_platform_sp->GetProcessInfo(pid, process_info); 390 return false; 391 } 392 393 uint32_t 394 RemoteAwarePlatform::FindProcesses(const ProcessInstanceInfoMatch &match_info, 395 ProcessInstanceInfoList &process_infos) { 396 if (IsHost()) 397 return Platform::FindProcesses(match_info, process_infos); 398 if (m_remote_platform_sp) 399 return m_remote_platform_sp->FindProcesses(match_info, process_infos); 400 return 0; 401 } 402 403 lldb::ProcessSP RemoteAwarePlatform::ConnectProcess(llvm::StringRef connect_url, 404 llvm::StringRef plugin_name, 405 Debugger &debugger, 406 Target *target, 407 Status &error) { 408 if (m_remote_platform_sp) 409 return m_remote_platform_sp->ConnectProcess(connect_url, plugin_name, 410 debugger, target, error); 411 return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, 412 error); 413 } 414 415 Status RemoteAwarePlatform::LaunchProcess(ProcessLaunchInfo &launch_info) { 416 Status error; 417 418 if (IsHost()) { 419 error = Platform::LaunchProcess(launch_info); 420 } else { 421 if (m_remote_platform_sp) 422 error = m_remote_platform_sp->LaunchProcess(launch_info); 423 else 424 error.SetErrorString("the platform is not currently connected"); 425 } 426 return error; 427 } 428 429 Status RemoteAwarePlatform::KillProcess(const lldb::pid_t pid) { 430 if (IsHost()) 431 return Platform::KillProcess(pid); 432 if (m_remote_platform_sp) 433 return m_remote_platform_sp->KillProcess(pid); 434 return Status("the platform is not currently connected"); 435 } 436 437 size_t RemoteAwarePlatform::ConnectToWaitingProcesses(Debugger &debugger, 438 Status &error) { 439 if (m_remote_platform_sp) 440 return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error); 441 return Platform::ConnectToWaitingProcesses(debugger, error); 442 } 443