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 // TODO: 64 bit systems should also advertize support for 32 bit arch 234 // unknown CPU, we just support the one arch 235 if (idx == 0) 236 { 237 arch = remote_arch; 238 return true; 239 } 240 return false; 241 } 242 243 size_t 244 PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) 245 { 246 // This isn't needed if the z/Z packets are supported in the GDB remote 247 // server. But we might need a packet to detect this. 248 return 0; 249 } 250 251 bool 252 PlatformRemoteGDBServer::GetRemoteOSVersion () 253 { 254 uint32_t major, minor, update; 255 if (m_gdb_client.GetOSVersion (major, minor, update)) 256 { 257 m_major_os_version = major; 258 m_minor_os_version = minor; 259 m_update_os_version = update; 260 return true; 261 } 262 return false; 263 } 264 265 bool 266 PlatformRemoteGDBServer::GetRemoteOSBuildString (std::string &s) 267 { 268 return m_gdb_client.GetOSBuildString (s); 269 } 270 271 bool 272 PlatformRemoteGDBServer::GetRemoteOSKernelDescription (std::string &s) 273 { 274 return m_gdb_client.GetOSKernelDescription (s); 275 } 276 277 // Remote Platform subclasses need to override this function 278 ArchSpec 279 PlatformRemoteGDBServer::GetRemoteSystemArchitecture () 280 { 281 return m_gdb_client.GetSystemArchitecture(); 282 } 283 284 lldb_private::ConstString 285 PlatformRemoteGDBServer::GetRemoteWorkingDirectory() 286 { 287 if (IsConnected()) 288 { 289 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 290 std::string cwd; 291 if (m_gdb_client.GetWorkingDir(cwd)) 292 { 293 ConstString working_dir(cwd.c_str()); 294 if (log) 295 log->Printf("PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", working_dir.GetCString()); 296 return working_dir; 297 } 298 else 299 { 300 return ConstString(); 301 } 302 } 303 else 304 { 305 return Platform::GetRemoteWorkingDirectory(); 306 } 307 } 308 309 bool 310 PlatformRemoteGDBServer::SetRemoteWorkingDirectory(const lldb_private::ConstString &path) 311 { 312 if (IsConnected()) 313 { 314 // Clear the working directory it case it doesn't get set correctly. This will 315 // for use to re-read it 316 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 317 if (log) 318 log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", path.GetCString()); 319 return m_gdb_client.SetWorkingDir(path.GetCString()) == 0; 320 } 321 else 322 return Platform::SetRemoteWorkingDirectory(path); 323 } 324 325 bool 326 PlatformRemoteGDBServer::IsConnected () const 327 { 328 return m_gdb_client.IsConnected(); 329 } 330 331 Error 332 PlatformRemoteGDBServer::ConnectRemote (Args& args) 333 { 334 Error error; 335 if (IsConnected()) 336 { 337 error.SetErrorStringWithFormat ("the platform is already connected to '%s', execute 'platform disconnect' to close the current connection", 338 GetHostname()); 339 } 340 else 341 { 342 if (args.GetArgumentCount() == 1) 343 { 344 const char *url = args.GetArgumentAtIndex(0); 345 m_gdb_client.SetConnection (new ConnectionFileDescriptor()); 346 347 // we're going to reuse the hostname when we connect to the debugserver 348 std::string scheme; 349 int port; 350 std::string path; 351 if ( !UriParser::Parse(url, scheme, m_platform_hostname, port, path) ) 352 { 353 error.SetErrorString("invalid uri"); 354 return error; 355 } 356 357 const ConnectionStatus status = m_gdb_client.Connect(url, &error); 358 if (status == eConnectionStatusSuccess) 359 { 360 if (m_gdb_client.HandshakeWithServer(&error)) 361 { 362 m_gdb_client.GetHostInfo(); 363 // If a working directory was set prior to connecting, send it down now 364 if (m_working_dir) 365 m_gdb_client.SetWorkingDir(m_working_dir.GetCString()); 366 } 367 else 368 { 369 m_gdb_client.Disconnect(); 370 if (error.Success()) 371 error.SetErrorString("handshake failed"); 372 } 373 } 374 } 375 else 376 { 377 error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); 378 } 379 } 380 381 return error; 382 } 383 384 Error 385 PlatformRemoteGDBServer::DisconnectRemote () 386 { 387 Error error; 388 m_gdb_client.Disconnect(&error); 389 return error; 390 } 391 392 const char * 393 PlatformRemoteGDBServer::GetHostname () 394 { 395 m_gdb_client.GetHostname (m_name); 396 if (m_name.empty()) 397 return NULL; 398 return m_name.c_str(); 399 } 400 401 const char * 402 PlatformRemoteGDBServer::GetUserName (uint32_t uid) 403 { 404 // Try and get a cache user name first 405 const char *cached_user_name = Platform::GetUserName(uid); 406 if (cached_user_name) 407 return cached_user_name; 408 std::string name; 409 if (m_gdb_client.GetUserName(uid, name)) 410 return SetCachedUserName(uid, name.c_str(), name.size()); 411 412 SetUserNameNotFound(uid); // Negative cache so we don't keep sending packets 413 return NULL; 414 } 415 416 const char * 417 PlatformRemoteGDBServer::GetGroupName (uint32_t gid) 418 { 419 const char *cached_group_name = Platform::GetGroupName(gid); 420 if (cached_group_name) 421 return cached_group_name; 422 std::string name; 423 if (m_gdb_client.GetGroupName(gid, name)) 424 return SetCachedGroupName(gid, name.c_str(), name.size()); 425 426 SetGroupNameNotFound(gid); // Negative cache so we don't keep sending packets 427 return NULL; 428 } 429 430 uint32_t 431 PlatformRemoteGDBServer::FindProcesses (const ProcessInstanceInfoMatch &match_info, 432 ProcessInstanceInfoList &process_infos) 433 { 434 return m_gdb_client.FindProcesses (match_info, process_infos); 435 } 436 437 bool 438 PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 439 { 440 return m_gdb_client.GetProcessInfo (pid, process_info); 441 } 442 443 444 Error 445 PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) 446 { 447 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 448 Error error; 449 450 if (log) 451 log->Printf ("PlatformRemoteGDBServer::%s() called", __FUNCTION__); 452 453 auto num_file_actions = launch_info.GetNumFileActions (); 454 for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) 455 { 456 const auto file_action = launch_info.GetFileActionAtIndex (i); 457 if (file_action->GetAction () != FileAction::eFileActionOpen) 458 continue; 459 switch(file_action->GetFD()) 460 { 461 case STDIN_FILENO: 462 m_gdb_client.SetSTDIN (file_action->GetPath()); 463 break; 464 case STDOUT_FILENO: 465 m_gdb_client.SetSTDOUT (file_action->GetPath()); 466 break; 467 case STDERR_FILENO: 468 m_gdb_client.SetSTDERR (file_action->GetPath()); 469 break; 470 } 471 } 472 473 m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)); 474 m_gdb_client.SetDetachOnError (launch_info.GetFlags().Test (eLaunchFlagDetachOnError)); 475 476 const char *working_dir = launch_info.GetWorkingDirectory(); 477 if (working_dir && working_dir[0]) 478 { 479 m_gdb_client.SetWorkingDir (working_dir); 480 } 481 482 // Send the environment and the program + arguments after we connect 483 const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector(); 484 485 if (envp) 486 { 487 const char *env_entry; 488 for (int i=0; (env_entry = envp[i]); ++i) 489 { 490 if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0) 491 break; 492 } 493 } 494 495 ArchSpec arch_spec = launch_info.GetArchitecture(); 496 const char *arch_triple = arch_spec.GetTriple().str().c_str(); 497 498 m_gdb_client.SendLaunchArchPacket(arch_triple); 499 if (log) 500 log->Printf ("PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); 501 502 int arg_packet_err; 503 { 504 // Scope for the scoped timeout object 505 GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_client, 5); 506 arg_packet_err = m_gdb_client.SendArgumentsPacket (launch_info); 507 } 508 509 if (arg_packet_err == 0) 510 { 511 std::string error_str; 512 if (m_gdb_client.GetLaunchSuccess (error_str)) 513 { 514 const auto pid = m_gdb_client.GetCurrentProcessID (false); 515 if (pid != LLDB_INVALID_PROCESS_ID) 516 { 517 launch_info.SetProcessID (pid); 518 if (log) 519 log->Printf ("PlatformRemoteGDBServer::%s() pid %" PRIu64 " launched successfully", __FUNCTION__, pid); 520 } 521 else 522 { 523 if (log) 524 log->Printf ("PlatformRemoteGDBServer::%s() launch succeeded but we didn't get a valid process id back!", __FUNCTION__); 525 error.SetErrorString ("failed to get PID"); 526 } 527 } 528 else 529 { 530 error.SetErrorString (error_str.c_str()); 531 if (log) 532 log->Printf ("PlatformRemoteGDBServer::%s() launch failed: %s", __FUNCTION__, error.AsCString ()); 533 } 534 } 535 else 536 { 537 error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err); 538 } 539 return error; 540 } 541 542 Error 543 PlatformRemoteGDBServer::KillProcess (const lldb::pid_t pid) 544 { 545 if (!KillSpawnedProcess(pid)) 546 return Error("failed to kill remote spawned process"); 547 return Error(); 548 } 549 550 lldb::ProcessSP 551 PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, 552 lldb_private::Debugger &debugger, 553 lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one 554 lldb_private::Error &error) 555 { 556 lldb::ProcessSP process_sp; 557 if (IsRemote()) 558 { 559 if (IsConnected()) 560 { 561 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 562 uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid); 563 564 if (port == 0) 565 { 566 error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); 567 } 568 else 569 { 570 if (target == NULL) 571 { 572 TargetSP new_target_sp; 573 574 error = debugger.GetTargetList().CreateTarget (debugger, 575 NULL, 576 NULL, 577 false, 578 NULL, 579 new_target_sp); 580 target = new_target_sp.get(); 581 } 582 else 583 error.Clear(); 584 585 if (target && error.Success()) 586 { 587 debugger.GetTargetList().SetSelectedTarget(target); 588 589 // The darwin always currently uses the GDB remote debugger plug-in 590 // so even when debugging locally we are debugging remotely! 591 process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL); 592 593 if (process_sp) 594 { 595 std::string connect_url = MakeGdbServerUrl(m_platform_hostname, port); 596 error = process_sp->ConnectRemote (nullptr, connect_url.c_str()); 597 // Retry the connect remote one time... 598 if (error.Fail()) 599 error = process_sp->ConnectRemote (nullptr, connect_url.c_str()); 600 if (error.Success()) 601 error = process_sp->Launch(launch_info); 602 else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 603 { 604 printf ("error: connect remote failed (%s)\n", error.AsCString()); 605 KillSpawnedProcess(debugserver_pid); 606 } 607 } 608 } 609 } 610 } 611 else 612 { 613 error.SetErrorString("not connected to remote gdb server"); 614 } 615 } 616 return process_sp; 617 618 } 619 620 uint16_t 621 PlatformRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid) 622 { 623 ArchSpec remote_arch = GetRemoteSystemArchitecture (); 624 llvm::Triple &remote_triple = remote_arch.GetTriple (); 625 if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS) 626 { 627 // When remote debugging to iOS, we use a USB mux that always talks 628 // to localhost, so we will need the remote debugserver to accept connections 629 // only from localhost, no matter what our current hostname is 630 return m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1"); 631 } 632 else 633 { 634 // All other hosts should use their actual hostname 635 return m_gdb_client.LaunchGDBserverAndGetPort (pid, NULL); 636 } 637 } 638 639 bool 640 PlatformRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid) 641 { 642 return m_gdb_client.KillSpawnedProcess (pid); 643 } 644 645 lldb::ProcessSP 646 PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info, 647 Debugger &debugger, 648 Target *target, // Can be NULL, if NULL create a new target, else use existing one 649 Error &error) 650 { 651 lldb::ProcessSP process_sp; 652 if (IsRemote()) 653 { 654 if (IsConnected()) 655 { 656 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 657 uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid); 658 659 if (port == 0) 660 { 661 error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); 662 } 663 else 664 { 665 if (target == NULL) 666 { 667 TargetSP new_target_sp; 668 669 error = debugger.GetTargetList().CreateTarget (debugger, 670 NULL, 671 NULL, 672 false, 673 NULL, 674 new_target_sp); 675 target = new_target_sp.get(); 676 } 677 else 678 error.Clear(); 679 680 if (target && error.Success()) 681 { 682 debugger.GetTargetList().SetSelectedTarget(target); 683 684 // The darwin always currently uses the GDB remote debugger plug-in 685 // so even when debugging locally we are debugging remotely! 686 process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); 687 688 if (process_sp) 689 { 690 std::string connect_url = MakeGdbServerUrl(m_platform_hostname, port); 691 error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); 692 if (error.Success()) 693 { 694 auto listener = attach_info.GetHijackListener(); 695 if (listener != nullptr) 696 process_sp->HijackProcessEvents(listener.get()); 697 error = process_sp->Attach(attach_info); 698 } 699 700 if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) 701 { 702 KillSpawnedProcess(debugserver_pid); 703 } 704 } 705 } 706 } 707 } 708 else 709 { 710 error.SetErrorString("not connected to remote gdb server"); 711 } 712 } 713 return process_sp; 714 } 715 716 Error 717 PlatformRemoteGDBServer::MakeDirectory (const char *path, uint32_t mode) 718 { 719 Error error = m_gdb_client.MakeDirectory(path,mode); 720 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 721 if (log) 722 log->Printf ("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) error = %u (%s)", path, mode, error.GetError(), error.AsCString()); 723 return error; 724 } 725 726 727 Error 728 PlatformRemoteGDBServer::GetFilePermissions (const char *path, uint32_t &file_permissions) 729 { 730 Error error = m_gdb_client.GetFilePermissions(path, file_permissions); 731 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 732 if (log) 733 log->Printf ("PlatformRemoteGDBServer::GetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", path, file_permissions, error.GetError(), error.AsCString()); 734 return error; 735 } 736 737 Error 738 PlatformRemoteGDBServer::SetFilePermissions (const char *path, uint32_t file_permissions) 739 { 740 Error error = m_gdb_client.SetFilePermissions(path, file_permissions); 741 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 742 if (log) 743 log->Printf ("PlatformRemoteGDBServer::SetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", path, file_permissions, error.GetError(), error.AsCString()); 744 return error; 745 } 746 747 748 lldb::user_id_t 749 PlatformRemoteGDBServer::OpenFile (const lldb_private::FileSpec& file_spec, 750 uint32_t flags, 751 uint32_t mode, 752 Error &error) 753 { 754 return m_gdb_client.OpenFile (file_spec, flags, mode, error); 755 } 756 757 bool 758 PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd, Error &error) 759 { 760 return m_gdb_client.CloseFile (fd, error); 761 } 762 763 lldb::user_id_t 764 PlatformRemoteGDBServer::GetFileSize (const lldb_private::FileSpec& file_spec) 765 { 766 return m_gdb_client.GetFileSize(file_spec); 767 } 768 769 uint64_t 770 PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd, 771 uint64_t offset, 772 void *dst, 773 uint64_t dst_len, 774 Error &error) 775 { 776 return m_gdb_client.ReadFile (fd, offset, dst, dst_len, error); 777 } 778 779 uint64_t 780 PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd, 781 uint64_t offset, 782 const void* src, 783 uint64_t src_len, 784 Error &error) 785 { 786 return m_gdb_client.WriteFile (fd, offset, src, src_len, error); 787 } 788 789 lldb_private::Error 790 PlatformRemoteGDBServer::PutFile (const lldb_private::FileSpec& source, 791 const lldb_private::FileSpec& destination, 792 uint32_t uid, 793 uint32_t gid) 794 { 795 return Platform::PutFile(source,destination,uid,gid); 796 } 797 798 Error 799 PlatformRemoteGDBServer::CreateSymlink (const char *src, // The name of the link is in src 800 const char *dst) // The symlink points to dst 801 { 802 Error error = m_gdb_client.CreateSymlink (src, dst); 803 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 804 if (log) 805 log->Printf ("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') error = %u (%s)", src, dst, error.GetError(), error.AsCString()); 806 return error; 807 } 808 809 Error 810 PlatformRemoteGDBServer::Unlink (const char *path) 811 { 812 Error error = m_gdb_client.Unlink (path); 813 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 814 if (log) 815 log->Printf ("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", path, error.GetError(), error.AsCString()); 816 return error; 817 } 818 819 bool 820 PlatformRemoteGDBServer::GetFileExists (const lldb_private::FileSpec& file_spec) 821 { 822 return m_gdb_client.GetFileExists (file_spec); 823 } 824 825 lldb_private::Error 826 PlatformRemoteGDBServer::RunShellCommand (const char *command, // Shouldn't be NULL 827 const char *working_dir, // Pass NULL to use the current working directory 828 int *status_ptr, // Pass NULL if you don't want the process exit status 829 int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 830 std::string *command_output, // Pass NULL if you don't want the command output 831 uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 832 { 833 return m_gdb_client.RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 834 } 835 836 void 837 PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames () 838 { 839 m_trap_handlers.push_back (ConstString ("_sigtramp")); 840 } 841