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