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