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