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