1 //===-- PlatformRemoteGDBServer.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 "PlatformRemoteGDBServer.h" 10 #include "lldb/Host/Config.h" 11 12 #include "lldb/Breakpoint/BreakpointLocation.h" 13 #include "lldb/Core/Debugger.h" 14 #include "lldb/Core/Module.h" 15 #include "lldb/Core/ModuleList.h" 16 #include "lldb/Core/ModuleSpec.h" 17 #include "lldb/Core/PluginManager.h" 18 #include "lldb/Core/StreamFile.h" 19 #include "lldb/Host/ConnectionFileDescriptor.h" 20 #include "lldb/Host/Host.h" 21 #include "lldb/Host/HostInfo.h" 22 #include "lldb/Host/PosixApi.h" 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/Target.h" 25 #include "lldb/Utility/FileSpec.h" 26 #include "lldb/Utility/Log.h" 27 #include "lldb/Utility/ProcessInfo.h" 28 #include "lldb/Utility/Status.h" 29 #include "lldb/Utility/StreamString.h" 30 #include "lldb/Utility/UriParser.h" 31 32 #include "Plugins/Process/Utility/GDBRemoteSignals.h" 33 #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" 34 35 using namespace lldb; 36 using namespace lldb_private; 37 using namespace lldb_private::platform_gdb_server; 38 39 LLDB_PLUGIN_DEFINE_ADV(PlatformRemoteGDBServer, PlatformGDB) 40 41 static bool g_initialized = false; 42 43 void PlatformRemoteGDBServer::Initialize() { 44 Platform::Initialize(); 45 46 if (!g_initialized) { 47 g_initialized = true; 48 PluginManager::RegisterPlugin( 49 PlatformRemoteGDBServer::GetPluginNameStatic(), 50 PlatformRemoteGDBServer::GetDescriptionStatic(), 51 PlatformRemoteGDBServer::CreateInstance); 52 } 53 } 54 55 void PlatformRemoteGDBServer::Terminate() { 56 if (g_initialized) { 57 g_initialized = false; 58 PluginManager::UnregisterPlugin(PlatformRemoteGDBServer::CreateInstance); 59 } 60 61 Platform::Terminate(); 62 } 63 64 PlatformSP PlatformRemoteGDBServer::CreateInstance(bool force, 65 const ArchSpec *arch) { 66 bool create = force; 67 if (!create) { 68 create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified(); 69 } 70 if (create) 71 return PlatformSP(new PlatformRemoteGDBServer()); 72 return PlatformSP(); 73 } 74 75 llvm::StringRef PlatformRemoteGDBServer::GetDescriptionStatic() { 76 return "A platform that uses the GDB remote protocol as the communication " 77 "transport."; 78 } 79 80 llvm::StringRef PlatformRemoteGDBServer::GetDescription() { 81 if (m_platform_description.empty()) { 82 if (IsConnected()) { 83 // Send the get description packet 84 } 85 } 86 87 if (!m_platform_description.empty()) 88 return m_platform_description.c_str(); 89 return GetDescriptionStatic(); 90 } 91 92 Status PlatformRemoteGDBServer::ResolveExecutable( 93 const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, 94 const FileSpecList *module_search_paths_ptr) { 95 // copied from PlatformRemoteiOS 96 97 Status error; 98 // Nothing special to do here, just use the actual file and architecture 99 100 ModuleSpec resolved_module_spec(module_spec); 101 102 // Resolve any executable within an apk on Android? 103 // Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); 104 105 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()) || 106 module_spec.GetUUID().IsValid()) { 107 if (resolved_module_spec.GetArchitecture().IsValid() || 108 resolved_module_spec.GetUUID().IsValid()) { 109 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 110 module_search_paths_ptr, nullptr, 111 nullptr); 112 113 if (exe_module_sp && exe_module_sp->GetObjectFile()) 114 return error; 115 exe_module_sp.reset(); 116 } 117 // No valid architecture was specified or the exact arch wasn't found so 118 // ask the platform for the architectures that we should be using (in the 119 // correct order) and see if we can find a match that way 120 StreamString arch_names; 121 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( 122 idx, resolved_module_spec.GetArchitecture()); 123 ++idx) { 124 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 125 module_search_paths_ptr, nullptr, 126 nullptr); 127 // Did we find an executable using one of the 128 if (error.Success()) { 129 if (exe_module_sp && exe_module_sp->GetObjectFile()) 130 break; 131 else 132 error.SetErrorToGenericError(); 133 } 134 135 if (idx > 0) 136 arch_names.PutCString(", "); 137 arch_names.PutCString( 138 resolved_module_spec.GetArchitecture().GetArchitectureName()); 139 } 140 141 if (error.Fail() || !exe_module_sp) { 142 if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) { 143 error.SetErrorStringWithFormatv( 144 "'{0}' doesn't contain any '{1}' platform architectures: {2}", 145 resolved_module_spec.GetFileSpec(), GetPluginName(), 146 arch_names.GetData()); 147 } else { 148 error.SetErrorStringWithFormat( 149 "'%s' is not readable", 150 resolved_module_spec.GetFileSpec().GetPath().c_str()); 151 } 152 } 153 } else { 154 error.SetErrorStringWithFormat( 155 "'%s' does not exist", 156 resolved_module_spec.GetFileSpec().GetPath().c_str()); 157 } 158 159 return error; 160 } 161 162 bool PlatformRemoteGDBServer::GetModuleSpec(const FileSpec &module_file_spec, 163 const ArchSpec &arch, 164 ModuleSpec &module_spec) { 165 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 166 167 const auto module_path = module_file_spec.GetPath(false); 168 169 if (!m_gdb_client.GetModuleInfo(module_file_spec, arch, module_spec)) { 170 LLDB_LOGF( 171 log, 172 "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s", 173 __FUNCTION__, module_path.c_str(), 174 arch.GetTriple().getTriple().c_str()); 175 return false; 176 } 177 178 if (log) { 179 StreamString stream; 180 module_spec.Dump(stream); 181 LLDB_LOGF(log, 182 "PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s", 183 __FUNCTION__, module_path.c_str(), 184 arch.GetTriple().getTriple().c_str(), stream.GetData()); 185 } 186 187 return true; 188 } 189 190 Status PlatformRemoteGDBServer::GetFileWithUUID(const FileSpec &platform_file, 191 const UUID *uuid_ptr, 192 FileSpec &local_file) { 193 // Default to the local case 194 local_file = platform_file; 195 return Status(); 196 } 197 198 /// Default Constructor 199 PlatformRemoteGDBServer::PlatformRemoteGDBServer() 200 : Platform(false), // This is a remote platform 201 m_gdb_client() { 202 m_gdb_client.SetPacketTimeout( 203 process_gdb_remote::ProcessGDBRemote::GetPacketTimeout()); 204 } 205 206 /// Destructor. 207 /// 208 /// The destructor is virtual since this class is designed to be 209 /// inherited from by the plug-in instance. 210 PlatformRemoteGDBServer::~PlatformRemoteGDBServer() = default; 211 212 bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex(uint32_t idx, 213 ArchSpec &arch) { 214 ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture(); 215 216 if (idx == 0) { 217 arch = remote_arch; 218 return arch.IsValid(); 219 } else if (idx == 1 && remote_arch.IsValid() && 220 remote_arch.GetTriple().isArch64Bit()) { 221 arch.SetTriple(remote_arch.GetTriple().get32BitArchVariant()); 222 return arch.IsValid(); 223 } 224 return false; 225 } 226 227 size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode( 228 Target &target, BreakpointSite *bp_site) { 229 // This isn't needed if the z/Z packets are supported in the GDB remote 230 // server. But we might need a packet to detect this. 231 return 0; 232 } 233 234 bool PlatformRemoteGDBServer::GetRemoteOSVersion() { 235 m_os_version = m_gdb_client.GetOSVersion(); 236 return !m_os_version.empty(); 237 } 238 239 llvm::Optional<std::string> PlatformRemoteGDBServer::GetRemoteOSBuildString() { 240 return m_gdb_client.GetOSBuildString(); 241 } 242 243 bool PlatformRemoteGDBServer::GetRemoteOSKernelDescription(std::string &s) { 244 return m_gdb_client.GetOSKernelDescription(s); 245 } 246 247 // Remote Platform subclasses need to override this function 248 ArchSpec PlatformRemoteGDBServer::GetRemoteSystemArchitecture() { 249 return m_gdb_client.GetSystemArchitecture(); 250 } 251 252 FileSpec PlatformRemoteGDBServer::GetRemoteWorkingDirectory() { 253 if (IsConnected()) { 254 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 255 FileSpec working_dir; 256 if (m_gdb_client.GetWorkingDir(working_dir) && log) 257 LLDB_LOGF(log, 258 "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", 259 working_dir.GetCString()); 260 return working_dir; 261 } else { 262 return Platform::GetRemoteWorkingDirectory(); 263 } 264 } 265 266 bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory( 267 const FileSpec &working_dir) { 268 if (IsConnected()) { 269 // Clear the working directory it case it doesn't get set correctly. This 270 // will for use to re-read it 271 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 272 LLDB_LOGF(log, "PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", 273 working_dir.GetCString()); 274 return m_gdb_client.SetWorkingDir(working_dir) == 0; 275 } else 276 return Platform::SetRemoteWorkingDirectory(working_dir); 277 } 278 279 bool PlatformRemoteGDBServer::IsConnected() const { 280 return m_gdb_client.IsConnected(); 281 } 282 283 Status PlatformRemoteGDBServer::ConnectRemote(Args &args) { 284 Status error; 285 if (IsConnected()) { 286 error.SetErrorStringWithFormat("the platform is already connected to '%s', " 287 "execute 'platform disconnect' to close the " 288 "current connection", 289 GetHostname()); 290 return error; 291 } 292 293 if (args.GetArgumentCount() != 1) { 294 error.SetErrorString( 295 "\"platform connect\" takes a single argument: <connect-url>"); 296 return error; 297 } 298 299 const char *url = args.GetArgumentAtIndex(0); 300 if (!url) 301 return Status("URL is null."); 302 303 llvm::Optional<URI> parsed_url = URI::Parse(url); 304 if (!parsed_url) 305 return Status("Invalid URL: %s", url); 306 307 // We're going to reuse the hostname when we connect to the debugserver. 308 m_platform_scheme = parsed_url->scheme.str(); 309 m_platform_hostname = parsed_url->hostname.str(); 310 311 m_gdb_client.SetConnection(std::make_unique<ConnectionFileDescriptor>()); 312 if (repro::Reproducer::Instance().IsReplaying()) { 313 error = m_gdb_replay_server.Connect(m_gdb_client); 314 if (error.Success()) 315 m_gdb_replay_server.StartAsyncThread(); 316 } else { 317 if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { 318 repro::GDBRemoteProvider &provider = 319 g->GetOrCreate<repro::GDBRemoteProvider>(); 320 m_gdb_client.SetPacketRecorder(provider.GetNewPacketRecorder()); 321 } 322 m_gdb_client.Connect(url, &error); 323 } 324 325 if (error.Fail()) 326 return error; 327 328 if (m_gdb_client.HandshakeWithServer(&error)) { 329 m_gdb_client.GetHostInfo(); 330 // If a working directory was set prior to connecting, send it down 331 // now. 332 if (m_working_dir) 333 m_gdb_client.SetWorkingDir(m_working_dir); 334 } else { 335 m_gdb_client.Disconnect(); 336 if (error.Success()) 337 error.SetErrorString("handshake failed"); 338 } 339 return error; 340 } 341 342 Status PlatformRemoteGDBServer::DisconnectRemote() { 343 Status error; 344 m_gdb_client.Disconnect(&error); 345 m_remote_signals_sp.reset(); 346 return error; 347 } 348 349 const char *PlatformRemoteGDBServer::GetHostname() { 350 m_gdb_client.GetHostname(m_name); 351 if (m_name.empty()) 352 return nullptr; 353 return m_name.c_str(); 354 } 355 356 llvm::Optional<std::string> 357 PlatformRemoteGDBServer::DoGetUserName(UserIDResolver::id_t uid) { 358 std::string name; 359 if (m_gdb_client.GetUserName(uid, name)) 360 return std::move(name); 361 return llvm::None; 362 } 363 364 llvm::Optional<std::string> 365 PlatformRemoteGDBServer::DoGetGroupName(UserIDResolver::id_t gid) { 366 std::string name; 367 if (m_gdb_client.GetGroupName(gid, name)) 368 return std::move(name); 369 return llvm::None; 370 } 371 372 uint32_t PlatformRemoteGDBServer::FindProcesses( 373 const ProcessInstanceInfoMatch &match_info, 374 ProcessInstanceInfoList &process_infos) { 375 return m_gdb_client.FindProcesses(match_info, process_infos); 376 } 377 378 bool PlatformRemoteGDBServer::GetProcessInfo( 379 lldb::pid_t pid, ProcessInstanceInfo &process_info) { 380 return m_gdb_client.GetProcessInfo(pid, process_info); 381 } 382 383 Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { 384 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 385 Status error; 386 387 LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() called", __FUNCTION__); 388 389 auto num_file_actions = launch_info.GetNumFileActions(); 390 for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) { 391 const auto file_action = launch_info.GetFileActionAtIndex(i); 392 if (file_action->GetAction() != FileAction::eFileActionOpen) 393 continue; 394 switch (file_action->GetFD()) { 395 case STDIN_FILENO: 396 m_gdb_client.SetSTDIN(file_action->GetFileSpec()); 397 break; 398 case STDOUT_FILENO: 399 m_gdb_client.SetSTDOUT(file_action->GetFileSpec()); 400 break; 401 case STDERR_FILENO: 402 m_gdb_client.SetSTDERR(file_action->GetFileSpec()); 403 break; 404 } 405 } 406 407 m_gdb_client.SetDisableASLR( 408 launch_info.GetFlags().Test(eLaunchFlagDisableASLR)); 409 m_gdb_client.SetDetachOnError( 410 launch_info.GetFlags().Test(eLaunchFlagDetachOnError)); 411 412 FileSpec working_dir = launch_info.GetWorkingDirectory(); 413 if (working_dir) { 414 m_gdb_client.SetWorkingDir(working_dir); 415 } 416 417 // Send the environment and the program + arguments after we connect 418 m_gdb_client.SendEnvironment(launch_info.GetEnvironment()); 419 420 ArchSpec arch_spec = launch_info.GetArchitecture(); 421 const char *arch_triple = arch_spec.GetTriple().str().c_str(); 422 423 m_gdb_client.SendLaunchArchPacket(arch_triple); 424 LLDB_LOGF( 425 log, 426 "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", 427 __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); 428 429 int arg_packet_err; 430 { 431 // Scope for the scoped timeout object 432 process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout( 433 m_gdb_client, std::chrono::seconds(5)); 434 arg_packet_err = m_gdb_client.SendArgumentsPacket(launch_info); 435 } 436 437 if (arg_packet_err == 0) { 438 std::string error_str; 439 if (m_gdb_client.GetLaunchSuccess(error_str)) { 440 const auto pid = m_gdb_client.GetCurrentProcessID(false); 441 if (pid != LLDB_INVALID_PROCESS_ID) { 442 launch_info.SetProcessID(pid); 443 LLDB_LOGF(log, 444 "PlatformRemoteGDBServer::%s() pid %" PRIu64 445 " launched successfully", 446 __FUNCTION__, pid); 447 } else { 448 LLDB_LOGF(log, 449 "PlatformRemoteGDBServer::%s() launch succeeded but we " 450 "didn't get a valid process id back!", 451 __FUNCTION__); 452 error.SetErrorString("failed to get PID"); 453 } 454 } else { 455 error.SetErrorString(error_str.c_str()); 456 LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() launch failed: %s", 457 __FUNCTION__, error.AsCString()); 458 } 459 } else { 460 error.SetErrorStringWithFormat("'A' packet returned an error: %i", 461 arg_packet_err); 462 } 463 return error; 464 } 465 466 Status PlatformRemoteGDBServer::KillProcess(const lldb::pid_t pid) { 467 if (!KillSpawnedProcess(pid)) 468 return Status("failed to kill remote spawned process"); 469 return Status(); 470 } 471 472 lldb::ProcessSP 473 PlatformRemoteGDBServer::DebugProcess(ProcessLaunchInfo &launch_info, 474 Debugger &debugger, Target &target, 475 Status &error) { 476 lldb::ProcessSP process_sp; 477 if (IsRemote()) { 478 if (IsConnected()) { 479 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 480 std::string connect_url; 481 if (!LaunchGDBServer(debugserver_pid, connect_url)) { 482 error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'", 483 GetHostname()); 484 } else { 485 // The darwin always currently uses the GDB remote debugger plug-in 486 // so even when debugging locally we are debugging remotely! 487 process_sp = target.CreateProcess(launch_info.GetListener(), 488 "gdb-remote", nullptr, true); 489 490 if (process_sp) { 491 error = process_sp->ConnectRemote(connect_url.c_str()); 492 // Retry the connect remote one time... 493 if (error.Fail()) 494 error = process_sp->ConnectRemote(connect_url.c_str()); 495 if (error.Success()) 496 error = process_sp->Launch(launch_info); 497 else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) { 498 printf("error: connect remote failed (%s)\n", error.AsCString()); 499 KillSpawnedProcess(debugserver_pid); 500 } 501 } 502 } 503 } else { 504 error.SetErrorString("not connected to remote gdb server"); 505 } 506 } 507 return process_sp; 508 } 509 510 bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, 511 std::string &connect_url) { 512 ArchSpec remote_arch = GetRemoteSystemArchitecture(); 513 llvm::Triple &remote_triple = remote_arch.GetTriple(); 514 515 uint16_t port = 0; 516 std::string socket_name; 517 bool launch_result = false; 518 if (remote_triple.getVendor() == llvm::Triple::Apple && 519 remote_triple.getOS() == llvm::Triple::IOS) { 520 // When remote debugging to iOS, we use a USB mux that always talks to 521 // localhost, so we will need the remote debugserver to accept connections 522 // only from localhost, no matter what our current hostname is 523 launch_result = 524 m_gdb_client.LaunchGDBServer("127.0.0.1", pid, port, socket_name); 525 } else { 526 // All other hosts should use their actual hostname 527 launch_result = 528 m_gdb_client.LaunchGDBServer(nullptr, pid, port, socket_name); 529 } 530 531 if (!launch_result) 532 return false; 533 534 connect_url = 535 MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port, 536 (socket_name.empty()) ? nullptr : socket_name.c_str()); 537 return true; 538 } 539 540 bool PlatformRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { 541 return m_gdb_client.KillSpawnedProcess(pid); 542 } 543 544 lldb::ProcessSP PlatformRemoteGDBServer::Attach( 545 ProcessAttachInfo &attach_info, Debugger &debugger, 546 Target *target, // Can be NULL, if NULL create a new target, else use 547 // existing one 548 Status &error) { 549 lldb::ProcessSP process_sp; 550 if (IsRemote()) { 551 if (IsConnected()) { 552 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 553 std::string connect_url; 554 if (!LaunchGDBServer(debugserver_pid, connect_url)) { 555 error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'", 556 GetHostname()); 557 } else { 558 if (target == nullptr) { 559 TargetSP new_target_sp; 560 561 error = debugger.GetTargetList().CreateTarget( 562 debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); 563 target = new_target_sp.get(); 564 } else 565 error.Clear(); 566 567 if (target && error.Success()) { 568 // The darwin always currently uses the GDB remote debugger plug-in 569 // so even when debugging locally we are debugging remotely! 570 process_sp = 571 target->CreateProcess(attach_info.GetListenerForProcess(debugger), 572 "gdb-remote", nullptr, true); 573 if (process_sp) { 574 error = process_sp->ConnectRemote(connect_url.c_str()); 575 if (error.Success()) { 576 ListenerSP listener_sp = attach_info.GetHijackListener(); 577 if (listener_sp) 578 process_sp->HijackProcessEvents(listener_sp); 579 error = process_sp->Attach(attach_info); 580 } 581 582 if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) { 583 KillSpawnedProcess(debugserver_pid); 584 } 585 } 586 } 587 } 588 } else { 589 error.SetErrorString("not connected to remote gdb server"); 590 } 591 } 592 return process_sp; 593 } 594 595 Status PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, 596 uint32_t mode) { 597 Status error = m_gdb_client.MakeDirectory(file_spec, mode); 598 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 599 LLDB_LOGF(log, 600 "PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) " 601 "error = %u (%s)", 602 file_spec.GetCString(), mode, error.GetError(), error.AsCString()); 603 return error; 604 } 605 606 Status PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec, 607 uint32_t &file_permissions) { 608 Status error = m_gdb_client.GetFilePermissions(file_spec, file_permissions); 609 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 610 LLDB_LOGF(log, 611 "PlatformRemoteGDBServer::GetFilePermissions(path='%s', " 612 "file_permissions=%o) error = %u (%s)", 613 file_spec.GetCString(), file_permissions, error.GetError(), 614 error.AsCString()); 615 return error; 616 } 617 618 Status PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec, 619 uint32_t file_permissions) { 620 Status error = m_gdb_client.SetFilePermissions(file_spec, file_permissions); 621 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 622 LLDB_LOGF(log, 623 "PlatformRemoteGDBServer::SetFilePermissions(path='%s', " 624 "file_permissions=%o) error = %u (%s)", 625 file_spec.GetCString(), file_permissions, error.GetError(), 626 error.AsCString()); 627 return error; 628 } 629 630 lldb::user_id_t PlatformRemoteGDBServer::OpenFile(const FileSpec &file_spec, 631 File::OpenOptions flags, 632 uint32_t mode, 633 Status &error) { 634 return m_gdb_client.OpenFile(file_spec, flags, mode, error); 635 } 636 637 bool PlatformRemoteGDBServer::CloseFile(lldb::user_id_t fd, Status &error) { 638 return m_gdb_client.CloseFile(fd, error); 639 } 640 641 lldb::user_id_t 642 PlatformRemoteGDBServer::GetFileSize(const FileSpec &file_spec) { 643 return m_gdb_client.GetFileSize(file_spec); 644 } 645 646 void PlatformRemoteGDBServer::AutoCompleteDiskFileOrDirectory( 647 CompletionRequest &request, bool only_dir) { 648 m_gdb_client.AutoCompleteDiskFileOrDirectory(request, only_dir); 649 } 650 651 uint64_t PlatformRemoteGDBServer::ReadFile(lldb::user_id_t fd, uint64_t offset, 652 void *dst, uint64_t dst_len, 653 Status &error) { 654 return m_gdb_client.ReadFile(fd, offset, dst, dst_len, error); 655 } 656 657 uint64_t PlatformRemoteGDBServer::WriteFile(lldb::user_id_t fd, uint64_t offset, 658 const void *src, uint64_t src_len, 659 Status &error) { 660 return m_gdb_client.WriteFile(fd, offset, src, src_len, error); 661 } 662 663 Status PlatformRemoteGDBServer::PutFile(const FileSpec &source, 664 const FileSpec &destination, 665 uint32_t uid, uint32_t gid) { 666 return Platform::PutFile(source, destination, uid, gid); 667 } 668 669 Status PlatformRemoteGDBServer::CreateSymlink( 670 const FileSpec &src, // The name of the link is in src 671 const FileSpec &dst) // The symlink points to dst 672 { 673 Status error = m_gdb_client.CreateSymlink(src, dst); 674 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 675 LLDB_LOGF(log, 676 "PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') " 677 "error = %u (%s)", 678 src.GetCString(), dst.GetCString(), error.GetError(), 679 error.AsCString()); 680 return error; 681 } 682 683 Status PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) { 684 Status error = m_gdb_client.Unlink(file_spec); 685 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 686 LLDB_LOGF(log, "PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", 687 file_spec.GetCString(), error.GetError(), error.AsCString()); 688 return error; 689 } 690 691 bool PlatformRemoteGDBServer::GetFileExists(const FileSpec &file_spec) { 692 return m_gdb_client.GetFileExists(file_spec); 693 } 694 695 Status PlatformRemoteGDBServer::RunShellCommand( 696 llvm::StringRef shell, llvm::StringRef command, 697 const FileSpec & 698 working_dir, // Pass empty FileSpec to use the current working directory 699 int *status_ptr, // Pass NULL if you don't want the process exit status 700 int *signo_ptr, // Pass NULL if you don't want the signal that caused the 701 // process to exit 702 std::string 703 *command_output, // Pass NULL if you don't want the command output 704 const Timeout<std::micro> &timeout) { 705 return m_gdb_client.RunShellCommand(command, working_dir, status_ptr, 706 signo_ptr, command_output, timeout); 707 } 708 709 void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() { 710 m_trap_handlers.push_back(ConstString("_sigtramp")); 711 } 712 713 const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() { 714 if (!IsConnected()) 715 return Platform::GetRemoteUnixSignals(); 716 717 if (m_remote_signals_sp) 718 return m_remote_signals_sp; 719 720 // If packet not implemented or JSON failed to parse, we'll guess the signal 721 // set based on the remote architecture. 722 m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture()); 723 724 StringExtractorGDBRemote response; 725 auto result = 726 m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo", response); 727 728 if (result != decltype(result)::Success || 729 response.GetResponseType() != response.eResponse) 730 return m_remote_signals_sp; 731 732 auto object_sp = 733 StructuredData::ParseJSON(std::string(response.GetStringRef())); 734 if (!object_sp || !object_sp->IsValid()) 735 return m_remote_signals_sp; 736 737 auto array_sp = object_sp->GetAsArray(); 738 if (!array_sp || !array_sp->IsValid()) 739 return m_remote_signals_sp; 740 741 auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>(); 742 743 bool done = array_sp->ForEach( 744 [&remote_signals_sp](StructuredData::Object *object) -> bool { 745 if (!object || !object->IsValid()) 746 return false; 747 748 auto dict = object->GetAsDictionary(); 749 if (!dict || !dict->IsValid()) 750 return false; 751 752 // Signal number and signal name are required. 753 int signo; 754 if (!dict->GetValueForKeyAsInteger("signo", signo)) 755 return false; 756 757 llvm::StringRef name; 758 if (!dict->GetValueForKeyAsString("name", name)) 759 return false; 760 761 // We can live without short_name, description, etc. 762 bool suppress{false}; 763 auto object_sp = dict->GetValueForKey("suppress"); 764 if (object_sp && object_sp->IsValid()) 765 suppress = object_sp->GetBooleanValue(); 766 767 bool stop{false}; 768 object_sp = dict->GetValueForKey("stop"); 769 if (object_sp && object_sp->IsValid()) 770 stop = object_sp->GetBooleanValue(); 771 772 bool notify{false}; 773 object_sp = dict->GetValueForKey("notify"); 774 if (object_sp && object_sp->IsValid()) 775 notify = object_sp->GetBooleanValue(); 776 777 std::string description{""}; 778 object_sp = dict->GetValueForKey("description"); 779 if (object_sp && object_sp->IsValid()) 780 description = std::string(object_sp->GetStringValue()); 781 782 remote_signals_sp->AddSignal(signo, name.str().c_str(), suppress, stop, 783 notify, description.c_str()); 784 return true; 785 }); 786 787 if (done) 788 m_remote_signals_sp = std::move(remote_signals_sp); 789 790 return m_remote_signals_sp; 791 } 792 793 std::string PlatformRemoteGDBServer::MakeGdbServerUrl( 794 const std::string &platform_scheme, const std::string &platform_hostname, 795 uint16_t port, const char *socket_name) { 796 const char *override_scheme = 797 getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME"); 798 const char *override_hostname = 799 getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME"); 800 const char *port_offset_c_str = 801 getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET"); 802 int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0; 803 804 return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(), 805 override_hostname ? override_hostname 806 : platform_hostname.c_str(), 807 port + port_offset, socket_name); 808 } 809 810 std::string PlatformRemoteGDBServer::MakeUrl(const char *scheme, 811 const char *hostname, 812 uint16_t port, const char *path) { 813 StreamString result; 814 result.Printf("%s://[%s]", scheme, hostname); 815 if (port != 0) 816 result.Printf(":%u", port); 817 if (path) 818 result.Write(path, strlen(path)); 819 return std::string(result.GetString()); 820 } 821 822 size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger &debugger, 823 Status &error) { 824 std::vector<std::string> connection_urls; 825 GetPendingGdbServerList(connection_urls); 826 827 for (size_t i = 0; i < connection_urls.size(); ++i) { 828 ConnectProcess(connection_urls[i].c_str(), "gdb-remote", debugger, nullptr, error); 829 if (error.Fail()) 830 return i; // We already connected to i process succsessfully 831 } 832 return connection_urls.size(); 833 } 834 835 size_t PlatformRemoteGDBServer::GetPendingGdbServerList( 836 std::vector<std::string> &connection_urls) { 837 std::vector<std::pair<uint16_t, std::string>> remote_servers; 838 m_gdb_client.QueryGDBServer(remote_servers); 839 for (const auto &gdbserver : remote_servers) { 840 const char *socket_name_cstr = 841 gdbserver.second.empty() ? nullptr : gdbserver.second.c_str(); 842 connection_urls.emplace_back( 843 MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, 844 gdbserver.first, socket_name_cstr)); 845 } 846 return connection_urls.size(); 847 } 848