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