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" 13254721Semaste 14254721Semaste// C Includes 15254721Semaste#include <sys/sysctl.h> 16254721Semaste 17254721Semaste// C++ Includes 18254721Semaste// Other libraries and framework includes 19254721Semaste// Project includes 20254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h" 21254721Semaste#include "lldb/Core/ConnectionFileDescriptor.h" 22254721Semaste#include "lldb/Core/Debugger.h" 23254721Semaste#include "lldb/Core/Error.h" 24254721Semaste#include "lldb/Core/Module.h" 25254721Semaste#include "lldb/Core/ModuleList.h" 26254721Semaste#include "lldb/Core/PluginManager.h" 27254721Semaste#include "lldb/Core/StreamString.h" 28254721Semaste#include "lldb/Host/FileSpec.h" 29254721Semaste#include "lldb/Host/Host.h" 30254721Semaste#include "lldb/Target/Process.h" 31254721Semaste#include "lldb/Target/Target.h" 32254721Semaste 33254721Semasteusing namespace lldb; 34254721Semasteusing namespace lldb_private; 35254721Semaste 36254721Semastestatic bool g_initialized = false; 37254721Semaste 38254721Semastevoid 39254721SemastePlatformRemoteGDBServer::Initialize () 40254721Semaste{ 41254721Semaste if (g_initialized == false) 42254721Semaste { 43254721Semaste g_initialized = true; 44254721Semaste PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetPluginNameStatic(), 45254721Semaste PlatformRemoteGDBServer::GetDescriptionStatic(), 46254721Semaste PlatformRemoteGDBServer::CreateInstance); 47254721Semaste } 48254721Semaste} 49254721Semaste 50254721Semastevoid 51254721SemastePlatformRemoteGDBServer::Terminate () 52254721Semaste{ 53254721Semaste if (g_initialized) 54254721Semaste { 55254721Semaste g_initialized = false; 56254721Semaste PluginManager::UnregisterPlugin (PlatformRemoteGDBServer::CreateInstance); 57254721Semaste } 58254721Semaste} 59254721Semaste 60254721SemastePlatform* 61254721SemastePlatformRemoteGDBServer::CreateInstance (bool force, const lldb_private::ArchSpec *arch) 62254721Semaste{ 63254721Semaste bool create = force; 64254721Semaste if (!create) 65254721Semaste { 66254721Semaste create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified(); 67254721Semaste } 68254721Semaste if (create) 69254721Semaste return new PlatformRemoteGDBServer (); 70254721Semaste return NULL; 71254721Semaste} 72254721Semaste 73254721Semaste 74254721Semastelldb_private::ConstString 75254721SemastePlatformRemoteGDBServer::GetPluginNameStatic() 76254721Semaste{ 77254721Semaste static ConstString g_name("remote-gdb-server"); 78254721Semaste return g_name; 79254721Semaste} 80254721Semaste 81254721Semasteconst char * 82254721SemastePlatformRemoteGDBServer::GetDescriptionStatic() 83254721Semaste{ 84254721Semaste return "A platform that uses the GDB remote protocol as the communication transport."; 85254721Semaste} 86254721Semaste 87254721Semasteconst char * 88254721SemastePlatformRemoteGDBServer::GetDescription () 89254721Semaste{ 90254721Semaste if (m_platform_description.empty()) 91254721Semaste { 92254721Semaste if (IsConnected()) 93254721Semaste { 94254721Semaste // Send the get description packet 95254721Semaste } 96254721Semaste } 97254721Semaste 98254721Semaste if (!m_platform_description.empty()) 99254721Semaste return m_platform_description.c_str(); 100254721Semaste return GetDescriptionStatic(); 101254721Semaste} 102254721Semaste 103254721SemasteError 104254721SemastePlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file, 105254721Semaste const ArchSpec &exe_arch, 106254721Semaste lldb::ModuleSP &exe_module_sp, 107254721Semaste const FileSpecList *module_search_paths_ptr) 108254721Semaste{ 109254721Semaste Error error; 110254721Semaste error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented"); 111254721Semaste return error; 112254721Semaste} 113254721Semaste 114254721SemasteError 115254721SemastePlatformRemoteGDBServer::GetFile (const FileSpec &platform_file, 116254721Semaste const UUID *uuid_ptr, 117254721Semaste FileSpec &local_file) 118254721Semaste{ 119254721Semaste // Default to the local case 120254721Semaste local_file = platform_file; 121254721Semaste return Error(); 122254721Semaste} 123254721Semaste 124254721Semaste//------------------------------------------------------------------ 125254721Semaste/// Default Constructor 126254721Semaste//------------------------------------------------------------------ 127254721SemastePlatformRemoteGDBServer::PlatformRemoteGDBServer () : 128254721Semaste Platform(false), // This is a remote platform 129254721Semaste m_gdb_client(true) 130254721Semaste{ 131254721Semaste} 132254721Semaste 133254721Semaste//------------------------------------------------------------------ 134254721Semaste/// Destructor. 135254721Semaste/// 136254721Semaste/// The destructor is virtual since this class is designed to be 137254721Semaste/// inherited from by the plug-in instance. 138254721Semaste//------------------------------------------------------------------ 139254721SemastePlatformRemoteGDBServer::~PlatformRemoteGDBServer() 140254721Semaste{ 141254721Semaste} 142254721Semaste 143254721Semastebool 144254721SemastePlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 145254721Semaste{ 146254721Semaste return false; 147254721Semaste} 148254721Semaste 149254721Semastesize_t 150254721SemastePlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) 151254721Semaste{ 152254721Semaste // This isn't needed if the z/Z packets are supported in the GDB remote 153254721Semaste // server. But we might need a packet to detect this. 154254721Semaste return 0; 155254721Semaste} 156254721Semaste 157254721Semastebool 158254721SemastePlatformRemoteGDBServer::GetRemoteOSVersion () 159254721Semaste{ 160254721Semaste uint32_t major, minor, update; 161254721Semaste if (m_gdb_client.GetOSVersion (major, minor, update)) 162254721Semaste { 163254721Semaste m_major_os_version = major; 164254721Semaste m_minor_os_version = minor; 165254721Semaste m_update_os_version = update; 166254721Semaste return true; 167254721Semaste } 168254721Semaste return false; 169254721Semaste} 170254721Semaste 171254721Semastebool 172254721SemastePlatformRemoteGDBServer::GetRemoteOSBuildString (std::string &s) 173254721Semaste{ 174254721Semaste return m_gdb_client.GetOSBuildString (s); 175254721Semaste} 176254721Semaste 177254721Semastebool 178254721SemastePlatformRemoteGDBServer::GetRemoteOSKernelDescription (std::string &s) 179254721Semaste{ 180254721Semaste return m_gdb_client.GetOSKernelDescription (s); 181254721Semaste} 182254721Semaste 183254721Semaste// Remote Platform subclasses need to override this function 184254721SemasteArchSpec 185254721SemastePlatformRemoteGDBServer::GetRemoteSystemArchitecture () 186254721Semaste{ 187254721Semaste return m_gdb_client.GetSystemArchitecture(); 188254721Semaste} 189254721Semaste 190254721Semastebool 191254721SemastePlatformRemoteGDBServer::IsConnected () const 192254721Semaste{ 193254721Semaste return m_gdb_client.IsConnected(); 194254721Semaste} 195254721Semaste 196254721SemasteError 197254721SemastePlatformRemoteGDBServer::ConnectRemote (Args& args) 198254721Semaste{ 199254721Semaste Error error; 200254721Semaste if (IsConnected()) 201254721Semaste { 202254721Semaste error.SetErrorStringWithFormat ("the platform is already connected to '%s', execute 'platform disconnect' to close the current connection", 203254721Semaste GetHostname()); 204254721Semaste } 205254721Semaste else 206254721Semaste { 207254721Semaste if (args.GetArgumentCount() == 1) 208254721Semaste { 209254721Semaste const char *url = args.GetArgumentAtIndex(0); 210254721Semaste m_gdb_client.SetConnection (new ConnectionFileDescriptor()); 211254721Semaste const ConnectionStatus status = m_gdb_client.Connect(url, &error); 212254721Semaste if (status == eConnectionStatusSuccess) 213254721Semaste { 214254721Semaste if (m_gdb_client.HandshakeWithServer(&error)) 215254721Semaste { 216254721Semaste m_gdb_client.QueryNoAckModeSupported(); 217254721Semaste m_gdb_client.GetHostInfo(); 218254721Semaste#if 0 219254721Semaste m_gdb_client.TestPacketSpeed(10000); 220254721Semaste#endif 221254721Semaste } 222254721Semaste else 223254721Semaste { 224254721Semaste m_gdb_client.Disconnect(); 225254721Semaste } 226254721Semaste } 227254721Semaste } 228254721Semaste else 229254721Semaste { 230254721Semaste error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); 231254721Semaste } 232254721Semaste } 233254721Semaste 234254721Semaste return error; 235254721Semaste} 236254721Semaste 237254721SemasteError 238254721SemastePlatformRemoteGDBServer::DisconnectRemote () 239254721Semaste{ 240254721Semaste Error error; 241254721Semaste m_gdb_client.Disconnect(&error); 242254721Semaste return error; 243254721Semaste} 244254721Semaste 245254721Semasteconst char * 246254721SemastePlatformRemoteGDBServer::GetHostname () 247254721Semaste{ 248254721Semaste m_gdb_client.GetHostname (m_name); 249254721Semaste if (m_name.empty()) 250254721Semaste return NULL; 251254721Semaste return m_name.c_str(); 252254721Semaste} 253254721Semaste 254254721Semasteconst char * 255254721SemastePlatformRemoteGDBServer::GetUserName (uint32_t uid) 256254721Semaste{ 257254721Semaste // Try and get a cache user name first 258254721Semaste const char *cached_user_name = Platform::GetUserName(uid); 259254721Semaste if (cached_user_name) 260254721Semaste return cached_user_name; 261254721Semaste std::string name; 262254721Semaste if (m_gdb_client.GetUserName(uid, name)) 263254721Semaste return SetCachedUserName(uid, name.c_str(), name.size()); 264254721Semaste 265254721Semaste SetUserNameNotFound(uid); // Negative cache so we don't keep sending packets 266254721Semaste return NULL; 267254721Semaste} 268254721Semaste 269254721Semasteconst char * 270254721SemastePlatformRemoteGDBServer::GetGroupName (uint32_t gid) 271254721Semaste{ 272254721Semaste const char *cached_group_name = Platform::GetGroupName(gid); 273254721Semaste if (cached_group_name) 274254721Semaste return cached_group_name; 275254721Semaste std::string name; 276254721Semaste if (m_gdb_client.GetGroupName(gid, name)) 277254721Semaste return SetCachedGroupName(gid, name.c_str(), name.size()); 278254721Semaste 279254721Semaste SetGroupNameNotFound(gid); // Negative cache so we don't keep sending packets 280254721Semaste return NULL; 281254721Semaste} 282254721Semaste 283254721Semasteuint32_t 284254721SemastePlatformRemoteGDBServer::FindProcesses (const ProcessInstanceInfoMatch &match_info, 285254721Semaste ProcessInstanceInfoList &process_infos) 286254721Semaste{ 287254721Semaste return m_gdb_client.FindProcesses (match_info, process_infos); 288254721Semaste} 289254721Semaste 290254721Semastebool 291254721SemastePlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 292254721Semaste{ 293254721Semaste return m_gdb_client.GetProcessInfo (pid, process_info); 294254721Semaste} 295254721Semaste 296254721Semaste 297254721SemasteError 298254721SemastePlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) 299254721Semaste{ 300254721Semaste Error error; 301254721Semaste lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 302254721Semaste 303254721Semaste m_gdb_client.SetSTDIN ("/dev/null"); 304254721Semaste m_gdb_client.SetSTDOUT ("/dev/null"); 305254721Semaste m_gdb_client.SetSTDERR ("/dev/null"); 306254721Semaste m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)); 307254721Semaste 308254721Semaste const char *working_dir = launch_info.GetWorkingDirectory(); 309254721Semaste if (working_dir && working_dir[0]) 310254721Semaste { 311254721Semaste m_gdb_client.SetWorkingDir (working_dir); 312254721Semaste } 313254721Semaste 314254721Semaste // Send the environment and the program + arguments after we connect 315254721Semaste const char **argv = launch_info.GetArguments().GetConstArgumentVector(); 316254721Semaste const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector(); 317254721Semaste 318254721Semaste if (envp) 319254721Semaste { 320254721Semaste const char *env_entry; 321254721Semaste for (int i=0; (env_entry = envp[i]); ++i) 322254721Semaste { 323254721Semaste if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0) 324254721Semaste break; 325254721Semaste } 326254721Semaste } 327254721Semaste const uint32_t old_packet_timeout = m_gdb_client.SetPacketTimeout (5); 328254721Semaste int arg_packet_err = m_gdb_client.SendArgumentsPacket (argv); 329254721Semaste m_gdb_client.SetPacketTimeout (old_packet_timeout); 330254721Semaste if (arg_packet_err == 0) 331254721Semaste { 332254721Semaste std::string error_str; 333254721Semaste if (m_gdb_client.GetLaunchSuccess (error_str)) 334254721Semaste { 335254721Semaste pid = m_gdb_client.GetCurrentProcessID (); 336254721Semaste if (pid != LLDB_INVALID_PROCESS_ID) 337254721Semaste launch_info.SetProcessID (pid); 338254721Semaste } 339254721Semaste else 340254721Semaste { 341254721Semaste error.SetErrorString (error_str.c_str()); 342254721Semaste } 343254721Semaste } 344254721Semaste else 345254721Semaste { 346254721Semaste error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err); 347254721Semaste } 348254721Semaste return error; 349254721Semaste} 350254721Semaste 351254721Semastelldb::ProcessSP 352254721SemastePlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info, 353254721Semaste Debugger &debugger, 354254721Semaste Target *target, // Can be NULL, if NULL create a new target, else use existing one 355254721Semaste Listener &listener, 356254721Semaste Error &error) 357254721Semaste{ 358254721Semaste lldb::ProcessSP process_sp; 359254721Semaste if (IsRemote()) 360254721Semaste { 361254721Semaste if (IsConnected()) 362254721Semaste { 363254721Semaste uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort(); 364254721Semaste 365254721Semaste if (port == 0) 366254721Semaste { 367254721Semaste error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); 368254721Semaste } 369254721Semaste else 370254721Semaste { 371254721Semaste if (target == NULL) 372254721Semaste { 373254721Semaste TargetSP new_target_sp; 374254721Semaste 375254721Semaste error = debugger.GetTargetList().CreateTarget (debugger, 376254721Semaste NULL, 377254721Semaste NULL, 378254721Semaste false, 379254721Semaste NULL, 380254721Semaste new_target_sp); 381254721Semaste target = new_target_sp.get(); 382254721Semaste } 383254721Semaste else 384254721Semaste error.Clear(); 385254721Semaste 386254721Semaste if (target && error.Success()) 387254721Semaste { 388254721Semaste debugger.GetTargetList().SetSelectedTarget(target); 389254721Semaste 390254721Semaste // The darwin always currently uses the GDB remote debugger plug-in 391254721Semaste // so even when debugging locally we are debugging remotely! 392254721Semaste process_sp = target->CreateProcess (listener, "gdb-remote", NULL); 393254721Semaste 394254721Semaste if (process_sp) 395254721Semaste { 396254721Semaste char connect_url[256]; 397254721Semaste const int connect_url_len = ::snprintf (connect_url, 398254721Semaste sizeof(connect_url), 399254721Semaste "connect://%s:%u", 400254721Semaste GetHostname (), 401254721Semaste port); 402254721Semaste assert (connect_url_len < (int)sizeof(connect_url)); 403254721Semaste error = process_sp->ConnectRemote (NULL, connect_url); 404254721Semaste if (error.Success()) 405254721Semaste error = process_sp->Attach(attach_info); 406254721Semaste } 407254721Semaste } 408254721Semaste } 409254721Semaste } 410254721Semaste else 411254721Semaste { 412254721Semaste error.SetErrorString("not connected to remote gdb server"); 413254721Semaste } 414254721Semaste } 415254721Semaste return process_sp; 416254721Semaste} 417254721Semaste 418254721Semaste 419