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