1254721Semaste//===-- PlatformRemoteGDBServer.cpp -----------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste#include "PlatformRemoteGDBServer.h" 13263363Semaste#include "lldb/Host/Config.h" 14254721Semaste 15254721Semaste// C Includes 16263363Semaste#ifndef LLDB_DISABLE_POSIX 17254721Semaste#include <sys/sysctl.h> 18263363Semaste#endif 19254721Semaste 20254721Semaste// C++ Includes 21254721Semaste// Other libraries and framework includes 22254721Semaste// Project includes 23254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h" 24254721Semaste#include "lldb/Core/ConnectionFileDescriptor.h" 25254721Semaste#include "lldb/Core/Debugger.h" 26254721Semaste#include "lldb/Core/Error.h" 27254721Semaste#include "lldb/Core/Module.h" 28254721Semaste#include "lldb/Core/ModuleList.h" 29254721Semaste#include "lldb/Core/PluginManager.h" 30254721Semaste#include "lldb/Core/StreamString.h" 31254721Semaste#include "lldb/Host/FileSpec.h" 32254721Semaste#include "lldb/Host/Host.h" 33254721Semaste#include "lldb/Target/Process.h" 34254721Semaste#include "lldb/Target/Target.h" 35254721Semaste 36254721Semasteusing namespace lldb; 37254721Semasteusing namespace lldb_private; 38254721Semaste 39254721Semastestatic bool g_initialized = false; 40254721Semaste 41254721Semastevoid 42254721SemastePlatformRemoteGDBServer::Initialize () 43254721Semaste{ 44254721Semaste if (g_initialized == false) 45254721Semaste { 46254721Semaste g_initialized = true; 47254721Semaste PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetPluginNameStatic(), 48254721Semaste PlatformRemoteGDBServer::GetDescriptionStatic(), 49254721Semaste PlatformRemoteGDBServer::CreateInstance); 50254721Semaste } 51254721Semaste} 52254721Semaste 53254721Semastevoid 54254721SemastePlatformRemoteGDBServer::Terminate () 55254721Semaste{ 56254721Semaste if (g_initialized) 57254721Semaste { 58254721Semaste g_initialized = false; 59254721Semaste PluginManager::UnregisterPlugin (PlatformRemoteGDBServer::CreateInstance); 60254721Semaste } 61254721Semaste} 62254721Semaste 63254721SemastePlatform* 64254721SemastePlatformRemoteGDBServer::CreateInstance (bool force, const lldb_private::ArchSpec *arch) 65254721Semaste{ 66254721Semaste bool create = force; 67254721Semaste if (!create) 68254721Semaste { 69254721Semaste create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified(); 70254721Semaste } 71254721Semaste if (create) 72254721Semaste return new PlatformRemoteGDBServer (); 73254721Semaste return NULL; 74254721Semaste} 75254721Semaste 76254721Semaste 77254721Semastelldb_private::ConstString 78254721SemastePlatformRemoteGDBServer::GetPluginNameStatic() 79254721Semaste{ 80254721Semaste static ConstString g_name("remote-gdb-server"); 81254721Semaste return g_name; 82254721Semaste} 83254721Semaste 84254721Semasteconst char * 85254721SemastePlatformRemoteGDBServer::GetDescriptionStatic() 86254721Semaste{ 87254721Semaste return "A platform that uses the GDB remote protocol as the communication transport."; 88254721Semaste} 89254721Semaste 90254721Semasteconst char * 91254721SemastePlatformRemoteGDBServer::GetDescription () 92254721Semaste{ 93254721Semaste if (m_platform_description.empty()) 94254721Semaste { 95254721Semaste if (IsConnected()) 96254721Semaste { 97254721Semaste // Send the get description packet 98254721Semaste } 99254721Semaste } 100254721Semaste 101254721Semaste if (!m_platform_description.empty()) 102254721Semaste return m_platform_description.c_str(); 103254721Semaste return GetDescriptionStatic(); 104254721Semaste} 105254721Semaste 106254721SemasteError 107254721SemastePlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file, 108254721Semaste const ArchSpec &exe_arch, 109254721Semaste lldb::ModuleSP &exe_module_sp, 110254721Semaste const FileSpecList *module_search_paths_ptr) 111254721Semaste{ 112254721Semaste Error error; 113263363Semaste //error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented"); 114263363Semaste if (m_gdb_client.GetFileExists(exe_file)) 115263363Semaste return error; 116263363Semaste // TODO: get the remote end to somehow resolve this file 117263363Semaste error.SetErrorString("file not found on remote end"); 118254721Semaste return error; 119254721Semaste} 120254721Semaste 121254721SemasteError 122269024SemastePlatformRemoteGDBServer::GetFileWithUUID (const FileSpec &platform_file, 123269024Semaste const UUID *uuid_ptr, 124269024Semaste FileSpec &local_file) 125254721Semaste{ 126254721Semaste // Default to the local case 127254721Semaste local_file = platform_file; 128254721Semaste return Error(); 129254721Semaste} 130254721Semaste 131254721Semaste//------------------------------------------------------------------ 132254721Semaste/// Default Constructor 133254721Semaste//------------------------------------------------------------------ 134254721SemastePlatformRemoteGDBServer::PlatformRemoteGDBServer () : 135254721Semaste Platform(false), // This is a remote platform 136254721Semaste m_gdb_client(true) 137254721Semaste{ 138254721Semaste} 139254721Semaste 140254721Semaste//------------------------------------------------------------------ 141254721Semaste/// Destructor. 142254721Semaste/// 143254721Semaste/// The destructor is virtual since this class is designed to be 144254721Semaste/// inherited from by the plug-in instance. 145254721Semaste//------------------------------------------------------------------ 146254721SemastePlatformRemoteGDBServer::~PlatformRemoteGDBServer() 147254721Semaste{ 148254721Semaste} 149254721Semaste 150254721Semastebool 151254721SemastePlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 152254721Semaste{ 153254721Semaste return false; 154254721Semaste} 155254721Semaste 156254721Semastesize_t 157254721SemastePlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) 158254721Semaste{ 159254721Semaste // This isn't needed if the z/Z packets are supported in the GDB remote 160254721Semaste // server. But we might need a packet to detect this. 161254721Semaste return 0; 162254721Semaste} 163254721Semaste 164254721Semastebool 165254721SemastePlatformRemoteGDBServer::GetRemoteOSVersion () 166254721Semaste{ 167254721Semaste uint32_t major, minor, update; 168254721Semaste if (m_gdb_client.GetOSVersion (major, minor, update)) 169254721Semaste { 170254721Semaste m_major_os_version = major; 171254721Semaste m_minor_os_version = minor; 172254721Semaste m_update_os_version = update; 173254721Semaste return true; 174254721Semaste } 175254721Semaste return false; 176254721Semaste} 177254721Semaste 178254721Semastebool 179254721SemastePlatformRemoteGDBServer::GetRemoteOSBuildString (std::string &s) 180254721Semaste{ 181254721Semaste return m_gdb_client.GetOSBuildString (s); 182254721Semaste} 183254721Semaste 184254721Semastebool 185254721SemastePlatformRemoteGDBServer::GetRemoteOSKernelDescription (std::string &s) 186254721Semaste{ 187254721Semaste return m_gdb_client.GetOSKernelDescription (s); 188254721Semaste} 189254721Semaste 190254721Semaste// Remote Platform subclasses need to override this function 191254721SemasteArchSpec 192254721SemastePlatformRemoteGDBServer::GetRemoteSystemArchitecture () 193254721Semaste{ 194254721Semaste return m_gdb_client.GetSystemArchitecture(); 195254721Semaste} 196254721Semaste 197263367Semastelldb_private::ConstString 198263367SemastePlatformRemoteGDBServer::GetRemoteWorkingDirectory() 199263367Semaste{ 200263367Semaste if (IsConnected()) 201263367Semaste { 202263367Semaste Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 203263367Semaste std::string cwd; 204263367Semaste if (m_gdb_client.GetWorkingDir(cwd)) 205263367Semaste { 206263367Semaste ConstString working_dir(cwd.c_str()); 207263367Semaste if (log) 208263367Semaste log->Printf("PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", working_dir.GetCString()); 209263367Semaste return working_dir; 210263367Semaste } 211263367Semaste else 212263367Semaste { 213263367Semaste return ConstString(); 214263367Semaste } 215263367Semaste } 216263367Semaste else 217263367Semaste { 218263367Semaste return Platform::GetRemoteWorkingDirectory(); 219263367Semaste } 220263367Semaste} 221263367Semaste 222254721Semastebool 223263367SemastePlatformRemoteGDBServer::SetRemoteWorkingDirectory(const lldb_private::ConstString &path) 224263367Semaste{ 225263367Semaste if (IsConnected()) 226263367Semaste { 227263367Semaste // Clear the working directory it case it doesn't get set correctly. This will 228263367Semaste // for use to re-read it 229263367Semaste Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 230263367Semaste if (log) 231263367Semaste log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", path.GetCString()); 232263367Semaste return m_gdb_client.SetWorkingDir(path.GetCString()) == 0; 233263367Semaste } 234263367Semaste else 235263367Semaste return Platform::SetRemoteWorkingDirectory(path); 236263367Semaste} 237263367Semaste 238263367Semastebool 239254721SemastePlatformRemoteGDBServer::IsConnected () const 240254721Semaste{ 241254721Semaste return m_gdb_client.IsConnected(); 242254721Semaste} 243254721Semaste 244254721SemasteError 245254721SemastePlatformRemoteGDBServer::ConnectRemote (Args& args) 246254721Semaste{ 247254721Semaste Error error; 248254721Semaste if (IsConnected()) 249254721Semaste { 250254721Semaste error.SetErrorStringWithFormat ("the platform is already connected to '%s', execute 'platform disconnect' to close the current connection", 251254721Semaste GetHostname()); 252254721Semaste } 253254721Semaste else 254254721Semaste { 255254721Semaste if (args.GetArgumentCount() == 1) 256254721Semaste { 257254721Semaste const char *url = args.GetArgumentAtIndex(0); 258254721Semaste m_gdb_client.SetConnection (new ConnectionFileDescriptor()); 259254721Semaste const ConnectionStatus status = m_gdb_client.Connect(url, &error); 260254721Semaste if (status == eConnectionStatusSuccess) 261254721Semaste { 262254721Semaste if (m_gdb_client.HandshakeWithServer(&error)) 263254721Semaste { 264254721Semaste m_gdb_client.GetHostInfo(); 265263367Semaste // If a working directory was set prior to connecting, send it down now 266263367Semaste if (m_working_dir) 267263367Semaste m_gdb_client.SetWorkingDir(m_working_dir.GetCString()); 268254721Semaste } 269254721Semaste else 270254721Semaste { 271254721Semaste m_gdb_client.Disconnect(); 272263367Semaste if (error.Success()) 273263367Semaste error.SetErrorString("handshake failed"); 274254721Semaste } 275254721Semaste } 276254721Semaste } 277254721Semaste else 278254721Semaste { 279254721Semaste error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); 280254721Semaste } 281254721Semaste } 282254721Semaste 283254721Semaste return error; 284254721Semaste} 285254721Semaste 286254721SemasteError 287254721SemastePlatformRemoteGDBServer::DisconnectRemote () 288254721Semaste{ 289254721Semaste Error error; 290254721Semaste m_gdb_client.Disconnect(&error); 291254721Semaste return error; 292254721Semaste} 293254721Semaste 294254721Semasteconst char * 295254721SemastePlatformRemoteGDBServer::GetHostname () 296254721Semaste{ 297254721Semaste m_gdb_client.GetHostname (m_name); 298254721Semaste if (m_name.empty()) 299254721Semaste return NULL; 300254721Semaste return m_name.c_str(); 301254721Semaste} 302254721Semaste 303254721Semasteconst char * 304254721SemastePlatformRemoteGDBServer::GetUserName (uint32_t uid) 305254721Semaste{ 306254721Semaste // Try and get a cache user name first 307254721Semaste const char *cached_user_name = Platform::GetUserName(uid); 308254721Semaste if (cached_user_name) 309254721Semaste return cached_user_name; 310254721Semaste std::string name; 311254721Semaste if (m_gdb_client.GetUserName(uid, name)) 312254721Semaste return SetCachedUserName(uid, name.c_str(), name.size()); 313254721Semaste 314254721Semaste SetUserNameNotFound(uid); // Negative cache so we don't keep sending packets 315254721Semaste return NULL; 316254721Semaste} 317254721Semaste 318254721Semasteconst char * 319254721SemastePlatformRemoteGDBServer::GetGroupName (uint32_t gid) 320254721Semaste{ 321254721Semaste const char *cached_group_name = Platform::GetGroupName(gid); 322254721Semaste if (cached_group_name) 323254721Semaste return cached_group_name; 324254721Semaste std::string name; 325254721Semaste if (m_gdb_client.GetGroupName(gid, name)) 326254721Semaste return SetCachedGroupName(gid, name.c_str(), name.size()); 327254721Semaste 328254721Semaste SetGroupNameNotFound(gid); // Negative cache so we don't keep sending packets 329254721Semaste return NULL; 330254721Semaste} 331254721Semaste 332254721Semasteuint32_t 333254721SemastePlatformRemoteGDBServer::FindProcesses (const ProcessInstanceInfoMatch &match_info, 334254721Semaste ProcessInstanceInfoList &process_infos) 335254721Semaste{ 336254721Semaste return m_gdb_client.FindProcesses (match_info, process_infos); 337254721Semaste} 338254721Semaste 339254721Semastebool 340254721SemastePlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 341254721Semaste{ 342254721Semaste return m_gdb_client.GetProcessInfo (pid, process_info); 343254721Semaste} 344254721Semaste 345254721Semaste 346254721SemasteError 347254721SemastePlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) 348254721Semaste{ 349254721Semaste Error error; 350254721Semaste lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 351254721Semaste 352254721Semaste m_gdb_client.SetSTDIN ("/dev/null"); 353254721Semaste m_gdb_client.SetSTDOUT ("/dev/null"); 354254721Semaste m_gdb_client.SetSTDERR ("/dev/null"); 355254721Semaste m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)); 356254721Semaste 357254721Semaste const char *working_dir = launch_info.GetWorkingDirectory(); 358254721Semaste if (working_dir && working_dir[0]) 359254721Semaste { 360254721Semaste m_gdb_client.SetWorkingDir (working_dir); 361254721Semaste } 362254721Semaste 363254721Semaste // Send the environment and the program + arguments after we connect 364254721Semaste const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector(); 365254721Semaste 366254721Semaste if (envp) 367254721Semaste { 368254721Semaste const char *env_entry; 369254721Semaste for (int i=0; (env_entry = envp[i]); ++i) 370254721Semaste { 371254721Semaste if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0) 372254721Semaste break; 373254721Semaste } 374254721Semaste } 375263363Semaste 376263363Semaste ArchSpec arch_spec = launch_info.GetArchitecture(); 377263363Semaste const char *arch_triple = arch_spec.GetTriple().str().c_str(); 378263363Semaste 379263363Semaste m_gdb_client.SendLaunchArchPacket(arch_triple); 380263363Semaste 381254721Semaste const uint32_t old_packet_timeout = m_gdb_client.SetPacketTimeout (5); 382263367Semaste int arg_packet_err = m_gdb_client.SendArgumentsPacket (launch_info); 383254721Semaste m_gdb_client.SetPacketTimeout (old_packet_timeout); 384254721Semaste if (arg_packet_err == 0) 385254721Semaste { 386254721Semaste std::string error_str; 387254721Semaste if (m_gdb_client.GetLaunchSuccess (error_str)) 388254721Semaste { 389254721Semaste pid = m_gdb_client.GetCurrentProcessID (); 390254721Semaste if (pid != LLDB_INVALID_PROCESS_ID) 391254721Semaste launch_info.SetProcessID (pid); 392254721Semaste } 393254721Semaste else 394254721Semaste { 395254721Semaste error.SetErrorString (error_str.c_str()); 396254721Semaste } 397254721Semaste } 398254721Semaste else 399254721Semaste { 400254721Semaste error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err); 401254721Semaste } 402254721Semaste return error; 403254721Semaste} 404254721Semaste 405254721Semastelldb::ProcessSP 406263367SemastePlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, 407263367Semaste lldb_private::Debugger &debugger, 408263367Semaste lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one 409263367Semaste lldb_private::Listener &listener, 410263367Semaste lldb_private::Error &error) 411263367Semaste{ 412263367Semaste lldb::ProcessSP process_sp; 413263367Semaste if (IsRemote()) 414263367Semaste { 415263367Semaste if (IsConnected()) 416263367Semaste { 417263367Semaste lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 418269024Semaste ArchSpec remote_arch = GetRemoteSystemArchitecture(); 419269024Semaste llvm::Triple &remote_triple = remote_arch.GetTriple(); 420269024Semaste uint16_t port = 0; 421269024Semaste if (remote_triple.getVendor() == llvm::Triple::Apple && remote_triple.getOS() == llvm::Triple::IOS) 422269024Semaste { 423269024Semaste // When remote debugging to iOS, we use a USB mux that always talks 424269024Semaste // to localhost, so we will need the remote debugserver to accept connections 425269024Semaste // only from localhost, no matter what our current hostname is 426269024Semaste port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "localhost"); 427269024Semaste } 428269024Semaste else 429269024Semaste { 430269024Semaste // All other hosts should use their actual hostname 431269024Semaste port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, NULL); 432269024Semaste } 433263367Semaste 434263367Semaste if (port == 0) 435263367Semaste { 436263367Semaste error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); 437263367Semaste } 438263367Semaste else 439263367Semaste { 440263367Semaste if (target == NULL) 441263367Semaste { 442263367Semaste TargetSP new_target_sp; 443263367Semaste 444263367Semaste error = debugger.GetTargetList().CreateTarget (debugger, 445263367Semaste NULL, 446263367Semaste NULL, 447263367Semaste false, 448263367Semaste NULL, 449263367Semaste new_target_sp); 450263367Semaste target = new_target_sp.get(); 451263367Semaste } 452263367Semaste else 453263367Semaste error.Clear(); 454263367Semaste 455263367Semaste if (target && error.Success()) 456263367Semaste { 457263367Semaste debugger.GetTargetList().SetSelectedTarget(target); 458263367Semaste 459263367Semaste // The darwin always currently uses the GDB remote debugger plug-in 460263367Semaste // so even when debugging locally we are debugging remotely! 461263367Semaste process_sp = target->CreateProcess (listener, "gdb-remote", NULL); 462263367Semaste 463263367Semaste if (process_sp) 464263367Semaste { 465263367Semaste char connect_url[256]; 466263367Semaste const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME"); 467263367Semaste const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET"); 468263367Semaste int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0; 469263367Semaste const int connect_url_len = ::snprintf (connect_url, 470263367Semaste sizeof(connect_url), 471263367Semaste "connect://%s:%u", 472263367Semaste override_hostname ? override_hostname : GetHostname (), 473263367Semaste port + port_offset); 474263367Semaste assert (connect_url_len < (int)sizeof(connect_url)); 475263367Semaste error = process_sp->ConnectRemote (NULL, connect_url); 476263367Semaste if (error.Success()) 477263367Semaste error = process_sp->Launch(launch_info); 478263367Semaste else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 479263367Semaste m_gdb_client.KillSpawnedProcess(debugserver_pid); 480263367Semaste } 481263367Semaste } 482263367Semaste } 483263367Semaste } 484263367Semaste else 485263367Semaste { 486263367Semaste error.SetErrorString("not connected to remote gdb server"); 487263367Semaste } 488263367Semaste } 489263367Semaste return process_sp; 490263367Semaste 491263367Semaste} 492263367Semaste 493263367Semastelldb::ProcessSP 494254721SemastePlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info, 495254721Semaste Debugger &debugger, 496254721Semaste Target *target, // Can be NULL, if NULL create a new target, else use existing one 497254721Semaste Listener &listener, 498254721Semaste Error &error) 499254721Semaste{ 500254721Semaste lldb::ProcessSP process_sp; 501254721Semaste if (IsRemote()) 502254721Semaste { 503254721Semaste if (IsConnected()) 504254721Semaste { 505263363Semaste lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 506269024Semaste ArchSpec remote_arch = GetRemoteSystemArchitecture(); 507269024Semaste llvm::Triple &remote_triple = remote_arch.GetTriple(); 508269024Semaste uint16_t port = 0; 509269024Semaste if (remote_triple.getVendor() == llvm::Triple::Apple && remote_triple.getOS() == llvm::Triple::IOS) 510269024Semaste { 511269024Semaste // When remote debugging to iOS, we use a USB mux that always talks 512269024Semaste // to localhost, so we will need the remote debugserver to accept connections 513269024Semaste // only from localhost, no matter what our current hostname is 514269024Semaste port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "localhost"); 515269024Semaste } 516269024Semaste else 517269024Semaste { 518269024Semaste // All other hosts should use their actual hostname 519269024Semaste port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, NULL); 520269024Semaste } 521254721Semaste 522254721Semaste if (port == 0) 523254721Semaste { 524254721Semaste error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); 525254721Semaste } 526254721Semaste else 527254721Semaste { 528254721Semaste if (target == NULL) 529254721Semaste { 530254721Semaste TargetSP new_target_sp; 531254721Semaste 532254721Semaste error = debugger.GetTargetList().CreateTarget (debugger, 533254721Semaste NULL, 534254721Semaste NULL, 535254721Semaste false, 536254721Semaste NULL, 537254721Semaste new_target_sp); 538254721Semaste target = new_target_sp.get(); 539254721Semaste } 540254721Semaste else 541254721Semaste error.Clear(); 542254721Semaste 543254721Semaste if (target && error.Success()) 544254721Semaste { 545254721Semaste debugger.GetTargetList().SetSelectedTarget(target); 546254721Semaste 547254721Semaste // The darwin always currently uses the GDB remote debugger plug-in 548254721Semaste // so even when debugging locally we are debugging remotely! 549254721Semaste process_sp = target->CreateProcess (listener, "gdb-remote", NULL); 550254721Semaste 551254721Semaste if (process_sp) 552254721Semaste { 553254721Semaste char connect_url[256]; 554263363Semaste const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME"); 555263363Semaste const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET"); 556263363Semaste int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0; 557254721Semaste const int connect_url_len = ::snprintf (connect_url, 558254721Semaste sizeof(connect_url), 559254721Semaste "connect://%s:%u", 560263363Semaste override_hostname ? override_hostname : GetHostname (), 561263363Semaste port + port_offset); 562254721Semaste assert (connect_url_len < (int)sizeof(connect_url)); 563254721Semaste error = process_sp->ConnectRemote (NULL, connect_url); 564254721Semaste if (error.Success()) 565254721Semaste error = process_sp->Attach(attach_info); 566263363Semaste else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 567263363Semaste { 568263363Semaste m_gdb_client.KillSpawnedProcess(debugserver_pid); 569263363Semaste } 570254721Semaste } 571254721Semaste } 572254721Semaste } 573254721Semaste } 574254721Semaste else 575254721Semaste { 576254721Semaste error.SetErrorString("not connected to remote gdb server"); 577254721Semaste } 578254721Semaste } 579254721Semaste return process_sp; 580254721Semaste} 581254721Semaste 582263367SemasteError 583263367SemastePlatformRemoteGDBServer::MakeDirectory (const char *path, uint32_t mode) 584263363Semaste{ 585263367Semaste Error error = m_gdb_client.MakeDirectory(path,mode); 586263367Semaste Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 587263367Semaste if (log) 588263367Semaste log->Printf ("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) error = %u (%s)", path, mode, error.GetError(), error.AsCString()); 589263367Semaste return error; 590263363Semaste} 591254721Semaste 592263367Semaste 593263367SemasteError 594263367SemastePlatformRemoteGDBServer::GetFilePermissions (const char *path, uint32_t &file_permissions) 595263367Semaste{ 596263367Semaste Error error = m_gdb_client.GetFilePermissions(path, file_permissions); 597263367Semaste Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 598263367Semaste if (log) 599263367Semaste log->Printf ("PlatformRemoteGDBServer::GetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", path, file_permissions, error.GetError(), error.AsCString()); 600263367Semaste return error; 601263367Semaste} 602263367Semaste 603263367SemasteError 604263367SemastePlatformRemoteGDBServer::SetFilePermissions (const char *path, uint32_t file_permissions) 605263367Semaste{ 606263367Semaste Error error = m_gdb_client.SetFilePermissions(path, file_permissions); 607263367Semaste Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 608263367Semaste if (log) 609263367Semaste log->Printf ("PlatformRemoteGDBServer::SetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", path, file_permissions, error.GetError(), error.AsCString()); 610263367Semaste return error; 611263367Semaste} 612263367Semaste 613263367Semaste 614263363Semastelldb::user_id_t 615263363SemastePlatformRemoteGDBServer::OpenFile (const lldb_private::FileSpec& file_spec, 616263363Semaste uint32_t flags, 617263367Semaste uint32_t mode, 618263363Semaste Error &error) 619263363Semaste{ 620263363Semaste return m_gdb_client.OpenFile (file_spec, flags, mode, error); 621263363Semaste} 622263363Semaste 623263363Semastebool 624263363SemastePlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd, Error &error) 625263363Semaste{ 626263363Semaste return m_gdb_client.CloseFile (fd, error); 627263363Semaste} 628263363Semaste 629263363Semastelldb::user_id_t 630263363SemastePlatformRemoteGDBServer::GetFileSize (const lldb_private::FileSpec& file_spec) 631263363Semaste{ 632263363Semaste return m_gdb_client.GetFileSize(file_spec); 633263363Semaste} 634263363Semaste 635263363Semasteuint64_t 636263363SemastePlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd, 637263363Semaste uint64_t offset, 638263363Semaste void *dst, 639263363Semaste uint64_t dst_len, 640263363Semaste Error &error) 641263363Semaste{ 642263363Semaste return m_gdb_client.ReadFile (fd, offset, dst, dst_len, error); 643263363Semaste} 644263363Semaste 645263363Semasteuint64_t 646263363SemastePlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd, 647263363Semaste uint64_t offset, 648263363Semaste const void* src, 649263363Semaste uint64_t src_len, 650263363Semaste Error &error) 651263363Semaste{ 652263363Semaste return m_gdb_client.WriteFile (fd, offset, src, src_len, error); 653263363Semaste} 654263363Semaste 655263363Semastelldb_private::Error 656263363SemastePlatformRemoteGDBServer::PutFile (const lldb_private::FileSpec& source, 657263363Semaste const lldb_private::FileSpec& destination, 658263363Semaste uint32_t uid, 659263363Semaste uint32_t gid) 660263363Semaste{ 661263363Semaste return Platform::PutFile(source,destination,uid,gid); 662263363Semaste} 663263363Semaste 664263367SemasteError 665263367SemastePlatformRemoteGDBServer::CreateSymlink (const char *src, // The name of the link is in src 666263367Semaste const char *dst) // The symlink points to dst 667263367Semaste{ 668263367Semaste Error error = m_gdb_client.CreateSymlink (src, dst); 669263367Semaste Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 670263367Semaste if (log) 671263367Semaste log->Printf ("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') error = %u (%s)", src, dst, error.GetError(), error.AsCString()); 672263367Semaste return error; 673263367Semaste} 674263367Semaste 675263367SemasteError 676263367SemastePlatformRemoteGDBServer::Unlink (const char *path) 677263367Semaste{ 678263367Semaste Error error = m_gdb_client.Unlink (path); 679263367Semaste Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 680263367Semaste if (log) 681263367Semaste log->Printf ("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", path, error.GetError(), error.AsCString()); 682263367Semaste return error; 683263367Semaste} 684263367Semaste 685263363Semastebool 686263363SemastePlatformRemoteGDBServer::GetFileExists (const lldb_private::FileSpec& file_spec) 687263363Semaste{ 688263363Semaste return m_gdb_client.GetFileExists (file_spec); 689263363Semaste} 690263363Semaste 691263363Semastelldb_private::Error 692263363SemastePlatformRemoteGDBServer::RunShellCommand (const char *command, // Shouldn't be NULL 693263363Semaste const char *working_dir, // Pass NULL to use the current working directory 694263363Semaste int *status_ptr, // Pass NULL if you don't want the process exit status 695263363Semaste int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 696263363Semaste std::string *command_output, // Pass NULL if you don't want the command output 697263363Semaste uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 698263363Semaste{ 699263363Semaste return m_gdb_client.RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 700263363Semaste} 701269024Semaste 702269024Semastevoid 703269024SemastePlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames () 704269024Semaste{ 705269024Semaste m_trap_handlers.push_back (ConstString ("_sigtramp")); 706269024Semaste} 707