124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- debugserver.cpp -----------------------------------------*- C++ -*-===//
224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//                     The LLVM Compiler Infrastructure
424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source
624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details.
724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===//
924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <sys/socket.h>
1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <sys/types.h>
1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <errno.h>
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <getopt.h>
1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <netinet/in.h>
1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <sys/select.h>
1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <sys/sysctl.h>
1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <string>
1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <vector>
1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <asl.h>
20b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton#include <arpa/inet.h>
21b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton#include <netdb.h>
22b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton#include <netinet/in.h>
23b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton#include <netinet/tcp.h>
24b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton#include <sys/un.h>
25b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton#include <sys/types.h>
2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "CFString.h"
2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "DNB.h"
2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "DNBLog.h"
3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "DNBTimer.h"
3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "PseudoTerminal.h"
3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "RNBContext.h"
3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "RNBServices.h"
3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "RNBSocket.h"
3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "RNBRemote.h"
3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "SysSignal.h"
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Global PID in case we get a signal and need to stop the process...
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_process_t g_pid = INVALID_NUB_PROCESS;
4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Run loop modes which determine which run loop function will be called
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnertypedef enum
4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    eRNBRunLoopModeInvalid = 0,
4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    eRNBRunLoopModeGetStartModeFromRemoteProtocol,
4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    eRNBRunLoopModeInferiorAttaching,
4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    eRNBRunLoopModeInferiorLaunching,
5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    eRNBRunLoopModeInferiorExecuting,
514fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton    eRNBRunLoopModePlatformMode,
5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    eRNBRunLoopModeExit
5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} RNBRunLoopMode;
5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Global Variables
5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBRemoteSP g_remoteSP;
6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic int g_lockdown_opt  = 0;
6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic int g_applist_opt = 0;
6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic nub_launch_flavor_t g_launch_flavor = eLaunchFlavorDefault;
630a7f75f9e375911ca91a884968b0efa36f18588dGreg Claytonint g_disable_aslr = 0;
6424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint g_isatty = 0;
6624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#define RNBLogSTDOUT(fmt, ...) do { if (g_isatty) { fprintf(stdout, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0)
6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#define RNBLogSTDERR(fmt, ...) do { if (g_isatty) { fprintf(stderr, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0)
6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Get our program path and arguments from the remote connection.
7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// We will need to start up the remote connection without a PID, get the
7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// arguments, wait for the new process to finish launching and hit its
7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// entry point,  and then return the run loop mode that should come next.
7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBRunLoopMode
7772e1c782ba1e4226da37af4722af608de9f39408Greg ClaytonRNBRunLoopGetStartModeFromRemote (RNBRemote* remote)
7824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
7924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    std::string packet;
8024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8172e1c782ba1e4226da37af4722af608de9f39408Greg Clayton    if (remote)
8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        RNBContext& ctx = remote->Context();
84a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton        uint32_t event_mask = RNBContext::event_read_packet_available |
85a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                              RNBContext::event_read_thread_exiting;
8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Spin waiting to get the A packet.
8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        while (1)
8924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...",__FUNCTION__, event_mask);
9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask);
9224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", __FUNCTION__, event_mask, set_events);
9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
94a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton            if (set_events & RNBContext::event_read_thread_exiting)
95a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton            {
96643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                RNBLogSTDERR ("error: packet read thread exited.\n");
97a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                return eRNBRunLoopModeExit;
98a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton            }
99a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton
10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (set_events & RNBContext::event_read_packet_available)
10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                rnb_err_t err = rnb_err;
10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                RNBRemote::PacketEnum type;
10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
10524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                err = remote->HandleReceivedPacket (&type);
10624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // check if we tried to attach to a process
1083a458eb1e413d39546b664813bba9f9ac292357eJim Ingham                if (type == RNBRemote::vattach || type == RNBRemote::vattachwait || type == RNBRemote::vattachorwait)
10924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
11024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (err == rnb_success)
111643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                    {
112643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                        RNBLogSTDOUT ("Attach succeeded, ready to debug.\n");
11324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        return eRNBRunLoopModeInferiorExecuting;
114643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                    }
11524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else
11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
117643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                        RNBLogSTDERR ("error: attach failed.\n");
11824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        return eRNBRunLoopModeExit;
11924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
12024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
12124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
12224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (err == rnb_success)
12324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
12424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // If we got our arguments we are ready to launch using the arguments
12524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // and any environment variables we received.
12624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (type == RNBRemote::set_argv)
12724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
12824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        return eRNBRunLoopModeInferiorLaunching;
12924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
13024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
13124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else if (err == rnb_not_connected)
13224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
133643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                    RNBLogSTDERR ("error: connection lost.\n");
13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    return eRNBRunLoopModeExit;
13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // a catch all for any other gdb remote packets that failed
13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Error getting packet.",__FUNCTION__);
14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    continue;
14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
14224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__);
14424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            else
14624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Connection closed before getting \"A\" packet.", __FUNCTION__);
14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                return eRNBRunLoopModeExit;
14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
15124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return eRNBRunLoopModeExit;
15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
15424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This run loop mode will wait for the process to launch and hit its
15824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// entry point. It will currently ignore all events except for the
15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// process state changed event, where it watches for the process stopped
16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// or crash process state.
16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
16224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBRunLoopMode
16372e1c782ba1e4226da37af4722af608de9f39408Greg ClaytonRNBRunLoopLaunchInferior (RNBRemote *remote, const char *stdin_path, const char *stdout_path, const char *stderr_path, bool no_stdio)
16424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
16524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBContext& ctx = remote->Context();
16624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
16724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // The Process stuff takes a c array, the RNBContext has a vector...
16824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // So make up a c array.
16924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
17024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Launching '%s'...", __FUNCTION__, ctx.ArgumentAtIndex(0));
17124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
17224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    size_t inferior_argc = ctx.ArgumentCount();
17324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Initialize inferior_argv with inferior_argc + 1 NULLs
17424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    std::vector<const char *> inferior_argv(inferior_argc + 1, NULL);
17524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
17624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    size_t i;
17724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    for (i = 0; i < inferior_argc; i++)
17824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        inferior_argv[i] = ctx.ArgumentAtIndex(i);
17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Pass the environment array the same way:
18124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    size_t inferior_envc = ctx.EnvironmentCount();
18324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Initialize inferior_argv with inferior_argc + 1 NULLs
18424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    std::vector<const char *> inferior_envp(inferior_envc + 1, NULL);
18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    for (i = 0; i < inferior_envc; i++)
18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        inferior_envp[i] = ctx.EnvironmentAtIndex(i);
18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Our launch type hasn't been set to anything concrete, so we need to
19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // figure our how we are going to launch automatically.
19124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
19224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_launch_flavor_t launch_flavor = g_launch_flavor;
19324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (launch_flavor == eLaunchFlavorDefault)
19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Our default launch method is posix spawn
19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        launch_flavor = eLaunchFlavorPosixSpawn;
19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1989a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda#ifdef WITH_SPRINGBOARD
19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Check if we have an app bundle, if so launch using SpringBoard.
20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (strstr(inferior_argv[0], ".app"))
20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
20224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            launch_flavor = eLaunchFlavorSpringBoard;
20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif
20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ctx.SetLaunchFlavor(launch_flavor);
20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char resolved_path[PATH_MAX];
20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // If we fail to resolve the path to our executable, then just use what we
21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // were given and hope for the best
21224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if ( !DNBResolveExecutablePath (inferior_argv[0], resolved_path, sizeof(resolved_path)) )
21324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ::strncpy(resolved_path, inferior_argv[0], sizeof(resolved_path));
21424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
21524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char launch_err_str[PATH_MAX];
21624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    launch_err_str[0] = '\0';
217fc30997d8b7927a92c5ec69908c98912e7fc100cJohnny Chen    const char * cwd = (ctx.GetWorkingDirPath() != NULL ? ctx.GetWorkingDirPath()
218fc30997d8b7927a92c5ec69908c98912e7fc100cJohnny Chen                                                        : ctx.GetWorkingDirectory());
21924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_process_t pid = DNBProcessLaunch (resolved_path,
22024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                          &inferior_argv[0],
22124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                          &inferior_envp[0],
222fc30997d8b7927a92c5ec69908c98912e7fc100cJohnny Chen                                          cwd,
22372e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                                          stdin_path,
22472e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                                          stdout_path,
22572e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                                          stderr_path,
226bd666017403e102e0ca435d6da585ff979f83598Caroline Tice                                          no_stdio,
22724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                          launch_flavor,
228452bf613496c7290c6b7a1a1eb28efbce63fd3b9Greg Clayton                                          g_disable_aslr,
22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                          launch_err_str,
23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                          sizeof(launch_err_str));
23124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    g_pid = pid;
23324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23437f1b929ece512d5ad525f319b8705c123ba9835Jason Molenda    if (pid == INVALID_NUB_PROCESS && strlen (launch_err_str) > 0)
23524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
23635c0edcedb2058ca8d0758f71ce958c23836d52dGreg Clayton        DNBLogThreaded ("%s DNBProcessLaunch() returned error: '%s'", __FUNCTION__, launch_err_str);
23724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ctx.LaunchStatus().SetError(-1, DNBError::Generic);
23824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ctx.LaunchStatus().SetErrorString(launch_err_str);
23924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
24037f1b929ece512d5ad525f319b8705c123ba9835Jason Molenda    else if (pid == INVALID_NUB_PROCESS)
24137f1b929ece512d5ad525f319b8705c123ba9835Jason Molenda    {
24237f1b929ece512d5ad525f319b8705c123ba9835Jason Molenda        DNBLogThreaded ("%s DNBProcessLaunch() failed to launch process, unknown failure", __FUNCTION__);
24337f1b929ece512d5ad525f319b8705c123ba9835Jason Molenda        ctx.LaunchStatus().SetError(-1, DNBError::Generic);
24437f1b929ece512d5ad525f319b8705c123ba9835Jason Molenda        ctx.LaunchStatus().SetErrorString(launch_err_str);
24537f1b929ece512d5ad525f319b8705c123ba9835Jason Molenda    }
24624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
247a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton    {
24824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ctx.LaunchStatus().Clear();
249a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton    }
25024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
25124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (remote->Comm().IsConnected())
25224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
25324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // It we are connected already, the next thing gdb will do is ask
25424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // whether the launch succeeded, and if not, whether there is an
25524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // error code.  So we need to fetch one packet from gdb before we wait
25624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // on the stop from the target.
25724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
25824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t event_mask = RNBContext::event_read_packet_available;
25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask);
26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (set_events & RNBContext::event_read_packet_available)
26224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            rnb_err_t err = rnb_err;
26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            RNBRemote::PacketEnum type;
26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            err = remote->HandleReceivedPacket (&type);
26724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (err != rnb_success)
26924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Error getting packet.", __FUNCTION__);
27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                return eRNBRunLoopModeExit;
27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (type != RNBRemote::query_launch_success)
27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Didn't get the expected qLaunchSuccess packet.", __FUNCTION__);
27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
27724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
27824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    while (pid != INVALID_NUB_PROCESS)
28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Wait for process to start up and hit entry point
28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...", __FUNCTION__, pid);
28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        nub_event_t set_events = DNBProcessWaitForEvents (pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, NULL);
28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x", __FUNCTION__, pid, set_events);
28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
28724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (set_events == 0)
28824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
28924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            pid = INVALID_NUB_PROCESS;
29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            g_pid = pid;
29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                nub_state_t pid_state = DNBProcessGetState (pid);
29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                DNBLogThreadedIf (LOG_RNB_EVENTS, "%s process %4.4x state changed (eEventProcessStateChanged): %s", __FUNCTION__, pid, DNBStateAsString(pid_state));
29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
29924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                switch (pid_state)
30024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    default:
30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateInvalid:
30324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateUnloaded:
30424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateAttaching:
30524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateLaunching:
30624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateSuspended:
30724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        break;  // Ignore
30824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
30924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateRunning:
31024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateStepping:
31124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        // Still waiting to stop at entry point...
31224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        break;
31324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
31424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateStopped:
31524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateCrashed:
31624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        ctx.SetProcessID(pid);
31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        return eRNBRunLoopModeInferiorExecuting;
31824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
31924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateDetached:
32024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    case eStateExited:
32124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        pid = INVALID_NUB_PROCESS;
32224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        g_pid = pid;
32324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        return eRNBRunLoopModeExit;
32424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
32524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
32624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
32724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DNBProcessResetEvents(pid, set_events);
32824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
32924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
33024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
33124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return eRNBRunLoopModeExit;
33224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
33324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
33424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
33524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
33624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This run loop mode will wait for the process to launch and hit its
33724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// entry point. It will currently ignore all events except for the
33824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// process state changed event, where it watches for the process stopped
33924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// or crash process state.
34024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
34124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBRunLoopMode
34272e1c782ba1e4226da37af4722af608de9f39408Greg ClaytonRNBRunLoopLaunchAttaching (RNBRemote *remote, nub_process_t attach_pid, nub_process_t& pid)
34324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
34424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBContext& ctx = remote->Context();
34524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
34624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__, attach_pid);
34724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char err_str[1024];
34824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    pid = DNBProcessAttach (attach_pid, NULL, err_str, sizeof(err_str));
34924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    g_pid = pid;
35024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
35124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (pid == INVALID_NUB_PROCESS)
35224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
35324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ctx.LaunchStatus().SetError(-1, DNBError::Generic);
35424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (err_str[0])
35524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            ctx.LaunchStatus().SetErrorString(err_str);
35624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return eRNBRunLoopModeExit;
35724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
35824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
35924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
36024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ctx.SetProcessID(pid);
36124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return eRNBRunLoopModeInferiorExecuting;
36224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
36324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
36424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
36524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
36624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Watch for signals:
36724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// SIGINT: so we can halt our inferior. (disabled for now)
36824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// SIGPIPE: in case our child process dies
36924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
37024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint g_sigint_received = 0;
37124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint g_sigpipe_received = 0;
37224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
37324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnersignal_handler(int signo)
37424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
37524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (%s)", __FUNCTION__, SysSignal::Name(signo));
37624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
37724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    switch (signo)
37824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
37924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case SIGINT:
38024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            g_sigint_received++;
38124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (g_pid != INVALID_NUB_PROCESS)
38224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
38324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Only send a SIGINT once...
38424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (g_sigint_received == 1)
38524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
38624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    switch (DNBProcessGetState (g_pid))
38724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
38824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        case eStateRunning:
38924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        case eStateStepping:
39024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            DNBProcessSignal (g_pid, SIGSTOP);
39124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            return;
392ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton                        default:
393ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton                            break;
39424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
39524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
39624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
39724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            exit (SIGINT);
39824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
39924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
40024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case SIGPIPE:
40124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            g_sigpipe_received = 1;
40224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
40324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
40424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
40524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
40624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Return the new run loop mode based off of the current process state
40724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBRunLoopMode
40872e1c782ba1e4226da37af4722af608de9f39408Greg ClaytonHandleProcessStateChange (RNBRemote *remote, bool initialize)
40924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
41024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBContext& ctx = remote->Context();
41124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_process_t pid = ctx.ProcessID();
41224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
41324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (pid == INVALID_NUB_PROCESS)
41424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
41524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s error: pid invalid, exiting...", __FUNCTION__);
41624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return eRNBRunLoopModeExit;
41724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
41824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_state_t pid_state = DNBProcessGetState (pid);
41924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
42024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i)  pid_state = %s", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state));
42124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
42224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    switch (pid_state)
42324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
42424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateInvalid:
42524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateUnloaded:
42624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Something bad happened
42724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return eRNBRunLoopModeExit;
42824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
42924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
43024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateAttaching:
43124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateLaunching:
43224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return eRNBRunLoopModeInferiorExecuting;
43324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
43424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateSuspended:
43524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateCrashed:
43624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateStopped:
43724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // If we stop due to a signal, so clear the fact that we got a SIGINT
43824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // so we can stop ourselves again (but only while our inferior
43924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // process is running..)
44024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            g_sigint_received = 0;
44124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (initialize == false)
44224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
44324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Compare the last stop count to our current notion of a stop count
44424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // to make sure we don't notify more than once for a given stop.
44524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount();
44624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                bool pid_stop_count_changed = ctx.SetProcessStopCount(DNBProcessGetStopCount(pid));
44724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (pid_stop_count_changed)
44824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
44924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    remote->FlushSTDIO();
45024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
45124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (ctx.GetProcessStopCount() == 1)
45224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
453851e30ec6a1b1d2c154bb7d69ed0d05b5fd14705Greg Clayton                        DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i)  pid_state = %s pid_stop_count %llu (old %llu)) Notify??? no, first stop...", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state), (uint64_t)ctx.GetProcessStopCount(), (uint64_t)prev_pid_stop_count);
45424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
45524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else
45624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
45724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
458851e30ec6a1b1d2c154bb7d69ed0d05b5fd14705Greg Clayton                        DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i)  pid_state = %s pid_stop_count %llu (old %llu)) Notify??? YES!!!", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state), (uint64_t)ctx.GetProcessStopCount(), (uint64_t)prev_pid_stop_count);
45924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        remote->NotifyThatProcessStopped ();
46024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
46124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
46224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
46324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
464851e30ec6a1b1d2c154bb7d69ed0d05b5fd14705Greg Clayton                    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i)  pid_state = %s pid_stop_count %llu (old %llu)) Notify??? skipping...", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state), (uint64_t)ctx.GetProcessStopCount(), (uint64_t)prev_pid_stop_count);
46524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
46624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
46724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return eRNBRunLoopModeInferiorExecuting;
46824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
46924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateStepping:
47024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateRunning:
47124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return eRNBRunLoopModeInferiorExecuting;
47224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
47324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        case eStateExited:
47424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            remote->HandlePacket_last_signal(NULL);
475ff39f746ebaa3710c44ba49bd9b0a6cf05f60a3fGreg Clayton        case eStateDetached:
47624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return eRNBRunLoopModeExit;
47724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
47824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
47924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Catch all...
48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return eRNBRunLoopModeExit;
48224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
48324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This function handles the case where our inferior program is stopped and
48424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// we are waiting for gdb remote protocol packets. When a packet occurs that
48524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// makes the inferior run, we need to leave this function with a new state
48624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// as the return code.
48724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerRNBRunLoopMode
48872e1c782ba1e4226da37af4722af608de9f39408Greg ClaytonRNBRunLoopInferiorExecuting (RNBRemote *remote)
48924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
49024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__);
49124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBContext& ctx = remote->Context();
49224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
49324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Init our mode and set 'is_running' based on the current process state
49424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBRunLoopMode mode = HandleProcessStateChange (remote, true);
49524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
49624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    while (ctx.ProcessID() != INVALID_NUB_PROCESS)
49724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
49824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
49924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        std::string set_events_str;
50024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t event_mask = ctx.NormalEventBits();
50124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
50224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (!ctx.ProcessStateRunning())
50324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
504fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            // Clear some bits if we are not running so we don't send any async packets
50524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            event_mask &= ~RNBContext::event_proc_stdio_available;
506fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            event_mask &= ~RNBContext::event_proc_profile_data;
50724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
50824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
50924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // We want to make sure we consume all process state changes and have
51024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // whomever is notifying us to wait for us to reset the event bit before
51124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // continuing.
51224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        //ctx.Events().SetResetAckMask (RNBContext::event_proc_state_changed);
51324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
51424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) ...",__FUNCTION__, event_mask);
51524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask);
51624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)",__FUNCTION__, event_mask, set_events, ctx.EventsAsString(set_events, set_events_str));
51724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
51824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (set_events)
51924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if ((set_events & RNBContext::event_proc_thread_exiting) ||
52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                (set_events & RNBContext::event_proc_stdio_available))
52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                remote->FlushSTDIO();
52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
526fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            if (set_events & RNBContext::event_proc_profile_data)
527fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            {
528fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong                remote->SendAsyncProfileData();
529fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong            }
530fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong
53124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (set_events & RNBContext::event_read_packet_available)
53224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
53324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // handleReceivedPacket will take care of resetting the
53424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // event_read_packet_available events when there are no more...
53524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                set_events ^= RNBContext::event_read_packet_available;
53624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (ctx.ProcessStateRunning())
53824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
53924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (remote->HandleAsyncPacket() == rnb_not_connected)
54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        // TODO: connect again? Exit?
54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (remote->HandleReceivedPacket() == rnb_not_connected)
54724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        // TODO: connect again? Exit?
54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (set_events & RNBContext::event_proc_state_changed)
55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                mode = HandleProcessStateChange (remote, false);
55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                ctx.Events().ResetEvents(RNBContext::event_proc_state_changed);
55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                set_events ^= RNBContext::event_proc_state_changed;
55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (set_events & RNBContext::event_proc_thread_exiting)
56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
56224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                mode = eRNBRunLoopModeExit;
56324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
56424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (set_events & RNBContext::event_read_thread_exiting)
56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
56724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Out remote packet receiving thread exited, exit for now.
56824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (ctx.HasValidProcessID())
56924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
57024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // TODO: We should add code that will leave the current process
57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // in its current state and listen for another connection...
57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (ctx.ProcessStateRunning())
57324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
574f44636bb5faa8ebf003c18e2ff20520bf7e5e938Jason Molenda                        DNBLog ("debugserver's event read thread is exiting, killing the inferior process.");
57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        DNBProcessKill (ctx.ProcessID());
57624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
57724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
57824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                mode = eRNBRunLoopModeExit;
57924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
58024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
58124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
58224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Reset all event bits that weren't reset for now...
58324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (set_events != 0)
58424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            ctx.Events().ResetEvents(set_events);
58524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
58624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (mode != eRNBRunLoopModeInferiorExecuting)
58724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
58824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
58924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
59024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return mode;
59124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
59224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
59324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5944fdf7602bedd8be648f3c549074cf13d90a05f03Greg ClaytonRNBRunLoopMode
5954fdf7602bedd8be648f3c549074cf13d90a05f03Greg ClaytonRNBRunLoopPlatform (RNBRemote *remote)
5964fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton{
5974fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton    RNBRunLoopMode mode = eRNBRunLoopModePlatformMode;
5984fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton    RNBContext& ctx = remote->Context();
5994fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton
6004fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton    while (mode == eRNBRunLoopModePlatformMode)
6014fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton    {
6024fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        std::string set_events_str;
6034fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        const uint32_t event_mask = RNBContext::event_read_packet_available |
6044fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                                    RNBContext::event_read_thread_exiting;
6054fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton
6064fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) ...",__FUNCTION__, event_mask);
6074fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask);
6084fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)",__FUNCTION__, event_mask, set_events, ctx.EventsAsString(set_events, set_events_str));
6094fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton
6104fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        if (set_events)
6114fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        {
6124fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            if (set_events & RNBContext::event_read_packet_available)
6134fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            {
6144fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                if (remote->HandleReceivedPacket() == rnb_not_connected)
6154fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                    mode = eRNBRunLoopModeExit;
6164fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            }
6174fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton
6184fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            if (set_events & RNBContext::event_read_thread_exiting)
6194fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            {
6204fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                mode = eRNBRunLoopModeExit;
6214fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            }
6224fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            ctx.Events().ResetEvents(set_events);
6234fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        }
6244fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton    }
6254fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton    return eRNBRunLoopModeExit;
6264fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton}
6274fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton
62824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
62924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Convenience function to set up the remote listening port
63024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Returns 1 for success 0 for failure.
63124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
63224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
633b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Claytonstatic void
634b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg ClaytonPortWasBoundCallback (const void *baton, in_port_t port)
635b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton{
636b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton    //::printf ("PortWasBoundCallback (baton = %p, port = %u)\n", baton, port);
637b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
638b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton    const char *unix_socket_name = (const char *)baton;
639b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
640b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton    if (unix_socket_name && unix_socket_name[0])
641b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton    {
642b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        // We were given a unix socket name to use to communicate the port
643b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        // that we ended up binding to back to our parent process
644b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        struct sockaddr_un saddr_un;
645b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        int s = ::socket (AF_UNIX, SOCK_STREAM, 0);
646b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        if (s < 0)
647b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        {
648b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton            perror("error: socket (AF_UNIX, SOCK_STREAM, 0)");
649b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton            exit(1);
650b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        }
651b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
652b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        saddr_un.sun_family = AF_UNIX;
653b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        ::strncpy(saddr_un.sun_path, unix_socket_name, sizeof(saddr_un.sun_path) - 1);
654b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
655b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        saddr_un.sun_len = SUN_LEN (&saddr_un);
656b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
657b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        if (::connect (s, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
658b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        {
659b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton            perror("error: connect (socket, &saddr_un, saddr_un_len)");
660b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton            exit(1);
661b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        }
662b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
663b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        //::printf ("connect () sucess!!\n");
664b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
665b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
666b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        // We were able to connect to the socket, now write our PID so whomever
667b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        // launched us will know this process's ID
668b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        RNBLogSTDOUT ("Listening to port %i...\n", port);
669b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
670b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        char pid_str[64];
671b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        const int pid_str_len = ::snprintf (pid_str, sizeof(pid_str), "%u", port);
672b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        const int bytes_sent = ::send (s, pid_str, pid_str_len, 0);
673b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
674b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        if (pid_str_len != bytes_sent)
675b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        {
676b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton            perror("error: send (s, pid_str, pid_str_len, 0)");
677b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton            exit (1);
678b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        }
679b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
680b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        //::printf ("send () sucess!!\n");
681b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
682b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        // We are done with the socket
683b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        close (s);
684b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton    }
685b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton}
686b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
68724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic int
688a619e8ec81ff9c838285105c034ee70a290be904Greg ClaytonStartListening (RNBRemote *remote, const char *listen_host, int listen_port, const char *unix_socket_name)
68924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
69072e1c782ba1e4226da37af4722af608de9f39408Greg Clayton    if (!remote->Comm().IsConnected())
69124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
692b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton        if (listen_port != 0)
693a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            RNBLogSTDOUT ("Listening to port %i for a connection from %s...\n", listen_port, listen_host ? listen_host : "localhost");
694a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton        if (remote->Comm().Listen(listen_host, listen_port, PortWasBoundCallback, unix_socket_name) != rnb_success)
69524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
69624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n");
69724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return 0;
69824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
69924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
70024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
70172e1c782ba1e4226da37af4722af608de9f39408Greg Clayton            remote->StartReadRemoteDataThread();
70224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
70324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
70424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return 1;
70524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
70624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
70724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
70824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// ASL Logging callback that can be registered with DNBLogSetLogCallback
70924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
71024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
71124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args)
71224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
71324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (format == NULL)
71424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return;
71524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    static aslmsg g_aslmsg = NULL;
71624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (g_aslmsg == NULL)
71724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
71824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        g_aslmsg = ::asl_new (ASL_TYPE_MSG);
71924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        char asl_key_sender[PATH_MAX];
72024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.%s-%g", DEBUGSERVER_PROGRAM_NAME, DEBUGSERVER_VERSION_NUM);
72124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ::asl_set (g_aslmsg, ASL_KEY_SENDER, asl_key_sender);
72224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
72324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
72424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int asl_level;
72524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (flags & DNBLOG_FLAG_FATAL)        asl_level = ASL_LEVEL_CRIT;
72624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else if (flags & DNBLOG_FLAG_ERROR)   asl_level = ASL_LEVEL_ERR;
72724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else if (flags & DNBLOG_FLAG_WARNING) asl_level = ASL_LEVEL_WARNING;
72824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else if (flags & DNBLOG_FLAG_VERBOSE) asl_level = ASL_LEVEL_WARNING; //ASL_LEVEL_INFO;
72924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else                                  asl_level = ASL_LEVEL_WARNING; //ASL_LEVEL_DEBUG;
73024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
73124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::asl_vlog (NULL, g_aslmsg, asl_level, format, args);
73224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
73324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
73424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
73524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// FILE based Logging callback that can be registered with
73624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// DNBLogSetLogCallback
73724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
73824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
73924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileLogCallback(void *baton, uint32_t flags, const char *format, va_list args)
74024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
74124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (baton == NULL || format == NULL)
74224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return;
74324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
74424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::vfprintf ((FILE *)baton, format, args);
74524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ::fprintf ((FILE *)baton, "\n");
74624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
74724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
74824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
74924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
75024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnershow_usage_and_exit (int exit_code)
75124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
75224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBLogSTDERR ("Usage:\n  %s host:port [program-name program-arg1 program-arg2 ...]\n", DEBUGSERVER_PROGRAM_NAME);
75324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBLogSTDERR ("  %s /path/file [program-name program-arg1 program-arg2 ...]\n", DEBUGSERVER_PROGRAM_NAME);
75424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBLogSTDERR ("  %s host:port --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME);
75524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBLogSTDERR ("  %s /path/file --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME);
75624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBLogSTDERR ("  %s host:port --attach=<process_name>\n", DEBUGSERVER_PROGRAM_NAME);
75724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBLogSTDERR ("  %s /path/file --attach=<process_name>\n", DEBUGSERVER_PROGRAM_NAME);
75824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    exit (exit_code);
75924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
76024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
76124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
76224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
7633f2f741bb533b78e2fac5332c4698338ea2fd3acGreg Clayton// option descriptors for getopt_long_only()
76424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
76524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic struct option g_long_options[] =
76624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
76724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "attach",             required_argument,  NULL,               'a' },
76820d338fad87eba91de65aa9bec76e01c04472848Greg Clayton    { "arch",               required_argument,  NULL,               'A' },
76924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "debug",              no_argument,        NULL,               'g' },
77024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "verbose",            no_argument,        NULL,               'v' },
77124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "lockdown",           no_argument,        &g_lockdown_opt,    1   },  // short option "-k"
77224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "applist",            no_argument,        &g_applist_opt,     1   },  // short option "-t"
77324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "log-file",           required_argument,  NULL,               'l' },
77424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "log-flags",          required_argument,  NULL,               'f' },
77524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "launch",             required_argument,  NULL,               'x' },  // Valid values are "auto", "posix-spawn", "fork-exec", "springboard" (arm only)
77624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "waitfor",            required_argument,  NULL,               'w' },  // Wait for a process whose name starts with ARG
77724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "waitfor-interval",   required_argument,  NULL,               'i' },  // Time in usecs to wait between sampling the pid list when waiting for a process by name
77824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "waitfor-duration",   required_argument,  NULL,               'd' },  // The time in seconds to wait for a process to show up by name
77924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { "native-regs",        no_argument,        NULL,               'r' },  // Specify to use the native registers instead of the gdb defaults for the architecture.
780de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton    { "stdio-path",         required_argument,  NULL,               's' },  // Set the STDIO path to be used when launching applications (STDIN, STDOUT and STDERR) (only if debugserver launches the process)
781de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton    { "stdin-path",         required_argument,  NULL,               'I' },  // Set the STDIN path to be used when launching applications (only if debugserver launches the process)
78246cd50c064711df3c688a3c3c16c0d0d5da29e49Johnny Chen    { "stdout-path",        required_argument,  NULL,               'O' },  // Set the STDOUT path to be used when launching applications (only if debugserver launches the process)
78346cd50c064711df3c688a3c3c16c0d0d5da29e49Johnny Chen    { "stderr-path",        required_argument,  NULL,               'E' },  // Set the STDERR path to be used when launching applications (only if debugserver launches the process)
784de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton    { "no-stdio",           no_argument,        NULL,               'n' },  // Do not set up any stdio (perhaps the program is a GUI program) (only if debugserver launches the process)
785de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton    { "setsid",             no_argument,        NULL,               'S' },  // call setsid() to make debugserver run in its own session
786452bf613496c7290c6b7a1a1eb28efbce63fd3b9Greg Clayton    { "disable-aslr",       no_argument,        NULL,               'D' },  // Use _POSIX_SPAWN_DISABLE_ASLR to avoid shared library randomization
787de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton    { "working-dir",        required_argument,  NULL,               'W' },  // The working directory that the inferior process should have (only if debugserver launches the process)
7884fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton    { "platform",           required_argument,  NULL,               'p' },  // Put this executable into a remote platform mode
789b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton    { "unix-socket",        required_argument,  NULL,               'u' },  // If we need to handshake with our parent process, an option will be passed down that specifies a unix socket name to use
79024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    { NULL,                 0,                  NULL,               0   }
79124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner};
79224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
79324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
79424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
79524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// main
79624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
79724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerint
79824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnermain (int argc, char *argv[])
79924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
8003646e6812b42737c578b99a57f686ae9de279cceJason Molenda    const char *argv_sub_zero = argv[0]; // save a copy of argv[0] for error reporting post-launch
8013646e6812b42737c578b99a57f686ae9de279cceJason Molenda
80224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    g_isatty = ::isatty (STDIN_FILENO);
80324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
80424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //  ::printf ("uid=%u euid=%u gid=%u egid=%u\n",
80524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //            getuid(),
80624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //            geteuid(),
80724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //            getgid(),
80824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //            getegid());
80924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
81024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
81124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //    signal (SIGINT, signal_handler);
81224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    signal (SIGPIPE, signal_handler);
81335c0edcedb2058ca8d0758f71ce958c23836d52dGreg Clayton    signal (SIGHUP, signal_handler);
81424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
815a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton    g_remoteSP.reset (new RNBRemote ());
816a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton
817a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton
818a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton    RNBRemote *remote = g_remoteSP.get();
819a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton    if (remote == NULL)
820a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton    {
821a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton        RNBLogSTDERR ("error: failed to create a remote connection class\n");
822a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton        return -1;
823a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton    }
824a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton
825a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton    RNBContext& ctx = remote->Context();
826a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton
82724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int i;
82824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int attach_pid = INVALID_NUB_PROCESS;
82924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
83024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FILE* log_file = NULL;
83124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t log_flags = 0;
83224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Parse our options
83324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int ch;
83424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int long_option_index = 0;
83524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int debug = 0;
83624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    std::string compile_options;
83724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    std::string waitfor_pid_name;           // Wait for a process that starts with this name
83824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    std::string attach_pid_name;
83920d338fad87eba91de65aa9bec76e01c04472848Greg Clayton    std::string arch_name;
840b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton    std::string working_dir;                // The new working directory to use for the inferior
841b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton    std::string unix_socket_name;           // If we need to handshake with our parent process, an option will be passed down that specifies a unix socket name to use
84224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    useconds_t waitfor_interval = 1000;     // Time in usecs between process lists polls when waiting for a process by name, default 1 msec.
84324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    useconds_t waitfor_duration = 0;        // Time in seconds to wait for a process by name, 0 means wait forever.
844bd666017403e102e0ca435d6da585ff979f83598Caroline Tice    bool no_stdio = false;
84524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
84624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#if !defined (DNBLOG_ENABLED)
84724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    compile_options += "(no-logging) ";
84824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif
84924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
85024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBRunLoopMode start_mode = eRNBRunLoopModeExit;
85124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
85204d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton    char short_options[512];
85304d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton    uint32_t short_options_idx = 0;
85404d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton
85504d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton     // Handle the two case that don't have short options in g_long_options
85604d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton    short_options[short_options_idx++] = 'k';
85704d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton    short_options[short_options_idx++] = 't';
85804d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton
85904d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton    for (i=0; g_long_options[i].name != NULL; ++i)
86004d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton    {
86104d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton        if (isalpha(g_long_options[i].val))
86204d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton        {
86304d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton            short_options[short_options_idx++] = g_long_options[i].val;
86404d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton            switch (g_long_options[i].has_arg)
86504d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton            {
86604d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton                default:
86704d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton                case no_argument:
86804d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton                    break;
86904d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton
87004d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton                case optional_argument:
87104d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton                    short_options[short_options_idx++] = ':';
87204d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton                    // Fall through to required_argument case below...
87304d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton                case required_argument:
87404d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton                    short_options[short_options_idx++] = ':';
87504d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton                    break;
87604d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton            }
87704d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton        }
87804d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton    }
87904d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton    // NULL terminate the short option string.
88004d397c5e251eaa5f520dbe6381d2a82303350e1Greg Clayton    short_options[short_options_idx++] = '\0';
8813f2f741bb533b78e2fac5332c4698338ea2fd3acGreg Clayton    while ((ch = getopt_long_only(argc, argv, short_options, g_long_options, &long_option_index)) != -1)
88224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
88324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
88424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    ch, (uint8_t)ch,
88524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    g_long_options[long_option_index].name,
88624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    g_long_options[long_option_index].has_arg ? '=' : ' ',
88724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    optarg ? optarg : "");
88824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (ch)
88924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
89024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 0:   // Any optional that auto set themselves will return 0
89124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
89224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
89320d338fad87eba91de65aa9bec76e01c04472848Greg Clayton            case 'A':
89420d338fad87eba91de65aa9bec76e01c04472848Greg Clayton                if (optarg && optarg[0])
89520d338fad87eba91de65aa9bec76e01c04472848Greg Clayton                    arch_name.assign(optarg);
89620d338fad87eba91de65aa9bec76e01c04472848Greg Clayton                break;
89720d338fad87eba91de65aa9bec76e01c04472848Greg Clayton
89824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'a':
89924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (optarg && optarg[0])
90024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
90124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (isdigit(optarg[0]))
90224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
90324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        char *end = NULL;
90424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        attach_pid = strtoul(optarg, &end, 0);
90524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (end == NULL || *end != '\0')
90624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
90724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            RNBLogSTDERR ("error: invalid pid option '%s'\n", optarg);
90824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            exit (4);
90924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
91024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
91124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else
91224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
91324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        attach_pid_name = optarg;
91424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
91524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    start_mode = eRNBRunLoopModeInferiorAttaching;
91624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
91724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
91824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
91924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // --waitfor=NAME
92024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'w':
92124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (optarg && optarg[0])
92224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
92324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    waitfor_pid_name = optarg;
92424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    start_mode = eRNBRunLoopModeInferiorAttaching;
92524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
92624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
92724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
92824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // --waitfor-interval=USEC
92924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'i':
93024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (optarg && optarg[0])
93124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
93224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char *end = NULL;
93324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    waitfor_interval = strtoul(optarg, &end, 0);
93424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (end == NULL || *end != '\0')
93524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
93624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("error: invalid waitfor-interval option value '%s'.\n", optarg);
93724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exit (6);
93824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
93924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
94024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
94124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
94224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // --waitfor-duration=SEC
94324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'd':
94424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (optarg && optarg[0])
94524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
94624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char *end = NULL;
94724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    waitfor_duration = strtoul(optarg, &end, 0);
94824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (end == NULL || *end != '\0')
94924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
95024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("error: invalid waitfor-duration option value '%s'.\n", optarg);
95124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exit (7);
95224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
95324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
95424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
95524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
956de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton            case 'W':
95772e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                if (optarg && optarg[0])
958de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton                    working_dir.assign(optarg);
95972e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                break;
96072e1c782ba1e4226da37af4722af608de9f39408Greg Clayton
96124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'x':
96224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (optarg && optarg[0])
96324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
96424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (strcasecmp(optarg, "auto") == 0)
96524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        g_launch_flavor = eLaunchFlavorDefault;
96624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else if (strcasestr(optarg, "posix") == optarg)
96724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        g_launch_flavor = eLaunchFlavorPosixSpawn;
96824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else if (strcasestr(optarg, "fork") == optarg)
96924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        g_launch_flavor = eLaunchFlavorForkExec;
9709a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda#ifdef WITH_SPRINGBOARD
97124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else if (strcasestr(optarg, "spring") == optarg)
97224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        g_launch_flavor = eLaunchFlavorSpringBoard;
97324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif
97424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else
97524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
97624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("error: invalid TYPE for the --launch=TYPE (-x TYPE) option: '%s'\n", optarg);
97724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("Valid values TYPE are:\n");
97824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("  auto    Auto-detect the best launch method to use.\n");
97924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("  posix   Launch the executable using posix_spawn.\n");
98024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("  fork    Launch the executable using fork and exec.\n");
9819a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda#ifdef WITH_SPRINGBOARD
98224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("  spring  Launch the executable through Springboard.\n");
98324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif
98424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exit (5);
98524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
98624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
98724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
98824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
98924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'l': // Set Log File
99024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (optarg && optarg[0])
99124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
99224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (strcasecmp(optarg, "stdout") == 0)
99324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        log_file = stdout;
99424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else if (strcasecmp(optarg, "stderr") == 0)
99524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        log_file = stderr;
99624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else
99743457c521adf1fd88bc30a99c3aed0796ede717eJim Ingham                    {
998de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton                        log_file = fopen(optarg, "w");
99943457c521adf1fd88bc30a99c3aed0796ede717eJim Ingham                        if (log_file != NULL)
100043457c521adf1fd88bc30a99c3aed0796ede717eJim Ingham                            setlinebuf(log_file);
100143457c521adf1fd88bc30a99c3aed0796ede717eJim Ingham                    }
100243457c521adf1fd88bc30a99c3aed0796ede717eJim Ingham
100324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (log_file == NULL)
100424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
100524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        const char *errno_str = strerror(errno);
100624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error");
100724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
100824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
100924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
101024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
101124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'f': // Log Flags
101224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (optarg && optarg[0])
101324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    log_flags = strtoul(optarg, NULL, 0);
101424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
101524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
101624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'g':
101724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                debug = 1;
10189a7749c6dd24f85e423066b8877bd9edc62f13cfJohnny Chen                DNBLogSetDebug(debug);
101924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
102024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
102124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 't':
102224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                g_applist_opt = 1;
102324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
102424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
102524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'k':
102624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                g_lockdown_opt = 1;
102724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
102824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
102924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'r':
1030a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                remote->SetUseNativeRegisters (true);
103124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
103224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
103324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'v':
103424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                DNBLogSetVerbose(1);
103524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
103624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
103724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 's':
1038a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                ctx.GetSTDIN().assign(optarg);
1039a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                ctx.GetSTDOUT().assign(optarg);
1040a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                ctx.GetSTDERR().assign(optarg);
104172e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                break;
104272e1c782ba1e4226da37af4722af608de9f39408Greg Clayton
104372e1c782ba1e4226da37af4722af608de9f39408Greg Clayton            case 'I':
1044a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                ctx.GetSTDIN().assign(optarg);
104572e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                break;
104672e1c782ba1e4226da37af4722af608de9f39408Greg Clayton
104772e1c782ba1e4226da37af4722af608de9f39408Greg Clayton            case 'O':
1048a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                ctx.GetSTDOUT().assign(optarg);
104972e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                break;
105072e1c782ba1e4226da37af4722af608de9f39408Greg Clayton
105172e1c782ba1e4226da37af4722af608de9f39408Greg Clayton            case 'E':
1052a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                ctx.GetSTDERR().assign(optarg);
105324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
105424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1055bd666017403e102e0ca435d6da585ff979f83598Caroline Tice            case 'n':
1056bd666017403e102e0ca435d6da585ff979f83598Caroline Tice                no_stdio = true;
1057bd666017403e102e0ca435d6da585ff979f83598Caroline Tice                break;
1058bd666017403e102e0ca435d6da585ff979f83598Caroline Tice
105924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case 'S':
106024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Put debugserver into a new session. Terminals group processes
106124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // into sessions and when a special terminal key sequences
106224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // (like control+c) are typed they can cause signals to go out to
106324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // all processes in a session. Using this --setsid (-S) option
106424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // will cause debugserver to run in its own sessions and be free
106524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // from such issues.
106624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                //
106724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // This is useful when debugserver is spawned from a command
106824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // line application that uses debugserver to do the debugging,
106924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // yet that application doesn't want debugserver receiving the
107024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // signals sent to the session (i.e. dying when anyone hits ^C).
107124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                setsid();
107224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
1073452bf613496c7290c6b7a1a1eb28efbce63fd3b9Greg Clayton            case 'D':
1074452bf613496c7290c6b7a1a1eb28efbce63fd3b9Greg Clayton                g_disable_aslr = 1;
1075452bf613496c7290c6b7a1a1eb28efbce63fd3b9Greg Clayton                break;
10764fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton
10774fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            case 'p':
10784fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                start_mode = eRNBRunLoopModePlatformMode;
10794fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                break;
1080b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton
1081b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton            case 'u':
1082b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton                unix_socket_name.assign (optarg);
1083b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton                break;
108424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
108524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
108620d338fad87eba91de65aa9bec76e01c04472848Greg Clayton
108720d338fad87eba91de65aa9bec76e01c04472848Greg Clayton    if (arch_name.empty())
108820d338fad87eba91de65aa9bec76e01c04472848Greg Clayton    {
1089a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton#if defined (__arm__)
109020d338fad87eba91de65aa9bec76e01c04472848Greg Clayton        arch_name.assign ("arm");
109120d338fad87eba91de65aa9bec76e01c04472848Greg Clayton#endif
109220d338fad87eba91de65aa9bec76e01c04472848Greg Clayton    }
109397bd5670cdb415a95c84050c20cfacce8ed178e7Greg Clayton    else
109497bd5670cdb415a95c84050c20cfacce8ed178e7Greg Clayton    {
109597bd5670cdb415a95c84050c20cfacce8ed178e7Greg Clayton        DNBSetArchitecture (arch_name.c_str());
109697bd5670cdb415a95c84050c20cfacce8ed178e7Greg Clayton    }
109724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1098a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton//    if (arch_name.empty())
1099a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton//    {
1100a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton//        fprintf(stderr, "error: no architecture was specified\n");
1101a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton//        exit (8);
1102a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton//    }
11033f2f741bb533b78e2fac5332c4698338ea2fd3acGreg Clayton    // Skip any options we consumed with getopt_long_only
110424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    argc -= optind;
110524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    argv += optind;
110624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
110724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1108de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton    if (!working_dir.empty())
110972e1c782ba1e4226da37af4722af608de9f39408Greg Clayton    {
1110de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton        if (remote->Context().SetWorkingDirectory (working_dir.c_str()) == false)
111172e1c782ba1e4226da37af4722af608de9f39408Greg Clayton        {
1112de915beb5febe597505ba33fdc2c39eea2abdbd4Greg Clayton            RNBLogSTDERR ("error: working directory doesn't exist '%s'.\n", working_dir.c_str());
111372e1c782ba1e4226da37af4722af608de9f39408Greg Clayton            exit (8);
111472e1c782ba1e4226da37af4722af608de9f39408Greg Clayton        }
111572e1c782ba1e4226da37af4722af608de9f39408Greg Clayton    }
111672e1c782ba1e4226da37af4722af608de9f39408Greg Clayton
111772e1c782ba1e4226da37af4722af608de9f39408Greg Clayton    remote->Initialize();
111820d338fad87eba91de65aa9bec76e01c04472848Greg Clayton
111924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // It is ok for us to set NULL as the logfile (this will disable any logging)
112024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
112124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (log_file != NULL)
112224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
112324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogSetLogCallback(FileLogCallback, log_file);
112424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // If our log file was set, yet we have no log flags, log everything!
112524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (log_flags == 0)
112624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            log_flags = LOG_ALL | LOG_RNB_ALL;
112724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
112824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogSetLogMask (log_flags);
112924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
113024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
113124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
113224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Enable DNB logging
113324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogSetLogCallback(ASLLogCallback, NULL);
113424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DNBLogSetLogMask (log_flags);
113524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
113624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
113724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
113824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (DNBLogEnabled())
113924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
114024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        for (i=0; i<argc; i++)
114124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DNBLogDebug("argv[%i] = %s", i, argv[i]);
114224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
114324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
114424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // as long as we're dropping remotenub in as a replacement for gdbserver,
114524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // explicitly note that this is not gdbserver.
114624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
114724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBLogSTDOUT ("%s-%g %sfor %s.\n",
114824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                  DEBUGSERVER_PROGRAM_NAME,
114924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                  DEBUGSERVER_VERSION_NUM,
115024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                  compile_options.c_str(),
115124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                  RNB_ARCH);
115224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1153a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton    std::string listen_host;
115424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int listen_port = INT32_MAX;
115524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char str[PATH_MAX];
11564a379b1194f3e6b308cd6e80b45d6ca5dd0aafd7Greg Clayton    str[0] = '\0';
115724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
115824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (g_lockdown_opt == 0 && g_applist_opt == 0)
115924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
116024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Make sure we at least have port
116124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (argc < 1)
116224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
116324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            show_usage_and_exit (1);
116424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
116524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // accept 'localhost:' prefix on port number
116624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
116724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        int items_scanned = ::sscanf (argv[0], "%[^:]:%i", str, &listen_port);
116824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (items_scanned == 2)
116924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
1170a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            listen_host = str;
1171a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            DNBLogDebug("host = '%s'  port = %i", listen_host.c_str(), listen_port);
117224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
117324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
117424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
1175a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            // No hostname means "localhost"
1176a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            int items_scanned = ::sscanf (argv[0], "%i", &listen_port);
1177a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            if (items_scanned == 1)
1178a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            {
1179a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton                listen_host = "localhost";
1180a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton                DNBLogDebug("host = '%s'  port = %i", listen_host.c_str(), listen_port);
1181a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            }
1182a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            else if (argv[0][0] == '/')
1183a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            {
1184a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton                listen_port = INT32_MAX;
1185a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton                strncpy(str, argv[0], sizeof(str));
1186a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            }
1187a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            else
1188a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            {
1189a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton                show_usage_and_exit (2);
1190a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton            }
119124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
119224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
119324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // We just used the 'host:port' or the '/path/file' arg...
119424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        argc--;
119524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        argv++;
119624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
119724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
119824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
119924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //  If we know we're waiting to attach, we don't need any of this other info.
12004fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton    if (start_mode != eRNBRunLoopModeInferiorAttaching &&
12014fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        start_mode != eRNBRunLoopModePlatformMode)
120224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
120324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (argc == 0 || g_lockdown_opt)
120424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
120524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (g_lockdown_opt != 0)
120624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
120724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Work around for SIGPIPE crashes due to posix_spawn issue.
120824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // We have to close STDOUT and STDERR, else the first time we
120924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // try and do any, we get SIGPIPE and die as posix_spawn is
121024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // doing bad things with our file descriptors at the moment.
121124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                int null = open("/dev/null", O_RDWR);
121224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                dup2(null, STDOUT_FILENO);
121324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                dup2(null, STDERR_FILENO);
121424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
121524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            else if (g_applist_opt != 0)
121624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
121724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // List all applications we are able to see
121824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                std::string applist_plist;
121924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                int err = ListApplications(applist_plist, false, false);
122024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (err == 0)
122124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
122224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    fputs (applist_plist.c_str(), stdout);
122324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
122424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
122524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
122624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    RNBLogSTDERR ("error: ListApplications returned error %i\n", err);
122724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
122824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Exit with appropriate error if we were asked to list the applications
122924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // with no other args were given (and we weren't trying to do this over
123024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // lockdown)
123124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                return err;
123224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
123324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
123424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DNBLogDebug("Get args from remote protocol...");
123524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            start_mode = eRNBRunLoopModeGetStartModeFromRemoteProtocol;
123624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
123724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
123824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
123924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            start_mode = eRNBRunLoopModeInferiorLaunching;
124024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Fill in the argv array in the context from the rest of our args.
124124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Skip the name of this executable and the port number
124224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            for (int i = 0; i < argc; i++)
124324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
124424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                DNBLogDebug("inferior_argv[%i] = '%s'", i, argv[i]);
124524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                ctx.PushArgument (argv[i]);
124624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
124724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
124824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
124924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
125024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (start_mode == eRNBRunLoopModeExit)
125124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return -1;
125224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
125324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    RNBRunLoopMode mode = start_mode;
125424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char err_str[1024] = {'\0'};
125524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
125624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    while (mode != eRNBRunLoopModeExit)
125724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
125824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (mode)
125924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
126024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case eRNBRunLoopModeGetStartModeFromRemoteProtocol:
12619a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda#ifdef WITH_LOCKDOWN
126224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (g_lockdown_opt)
126324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
126472e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                    if (!remote->Comm().IsConnected())
126524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
126672e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        if (remote->Comm().ConnectToService () != rnb_success)
126724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
126824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n");
126924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            mode = eRNBRunLoopModeExit;
127024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
127124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        else if (g_applist_opt != 0)
127224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
127324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            // List all applications we are able to see
127424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            std::string applist_plist;
127524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            if (ListApplications(applist_plist, false, false) == 0)
127624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
127724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                DNBLogDebug("Task list: %s", applist_plist.c_str());
127824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
127972e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                                remote->Comm().Write(applist_plist.c_str(), applist_plist.size());
128024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                // Issue a read that will never yield any data until the other side
128124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                // closes the socket so this process doesn't just exit and cause the
128224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                // socket to close prematurely on the other end and cause data loss.
128324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                std::string buf;
128472e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                                remote->Comm().Read(buf);
128524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
128672e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                            remote->Comm().Disconnect(false);
128724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            mode = eRNBRunLoopModeExit;
128824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            break;
128924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
129024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        else
129124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
129224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            // Start watching for remote packets
129372e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                            remote->StartReadRemoteDataThread();
129424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
129524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
129624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
129724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
129824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif
12994fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                if (listen_port != INT32_MAX)
13004fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                {
1301a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton                    if (!StartListening (remote, listen_host.c_str(), listen_port, unix_socket_name.c_str()))
13024fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                        mode = eRNBRunLoopModeExit;
13034fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                }
13044fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                else if (str[0] == '/')
13054fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                {
13064fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                    if (remote->Comm().OpenFile (str))
13074fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                        mode = eRNBRunLoopModeExit;
13084fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                }
13094fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton
131024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (mode != eRNBRunLoopModeExit)
131124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
131224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    RNBLogSTDOUT ("Got a connection, waiting for process information for launching or attaching.\n");
131324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
131472e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                    mode = RNBRunLoopGetStartModeFromRemote (remote);
131524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
131624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
131724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
131824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case eRNBRunLoopModeInferiorAttaching:
131924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (!waitfor_pid_name.empty())
132024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
132124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // Set our end wait time if we are using a waitfor-duration
132224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // option that may have been specified
132324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    struct timespec attach_timeout_abstime, *timeout_ptr = NULL;
132424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (waitfor_duration != 0)
132524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
132624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, 0);
132724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        timeout_ptr = &attach_timeout_abstime;
132824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
132924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    nub_launch_flavor_t launch_flavor = g_launch_flavor;
133024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (launch_flavor == eLaunchFlavorDefault)
133124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
133224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        // Our default launch method is posix spawn
133324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        launch_flavor = eLaunchFlavorPosixSpawn;
133424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
13359a5bbd2a14cacac731424f7a253f6cc16b22c10aJason Molenda#ifdef WITH_SPRINGBOARD
133624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        // Check if we have an app bundle, if so launch using SpringBoard.
133724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (waitfor_pid_name.find (".app") != std::string::npos)
133824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
133924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            launch_flavor = eLaunchFlavorSpringBoard;
134024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
134124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif
134224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
134324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
134424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    ctx.SetLaunchFlavor(launch_flavor);
13453a458eb1e413d39546b664813bba9f9ac292357eJim Ingham                    bool ignore_existing = false;
1346643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                    RNBLogSTDOUT ("Waiting to attach to process %s...\n", waitfor_pid_name.c_str());
13473a458eb1e413d39546b664813bba9f9ac292357eJim Ingham                    nub_process_t pid = DNBProcessAttachWait (waitfor_pid_name.c_str(), launch_flavor, ignore_existing, timeout_ptr, waitfor_interval, err_str, sizeof(err_str));
134824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    g_pid = pid;
134924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
135024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (pid == INVALID_NUB_PROCESS)
135124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
135224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        ctx.LaunchStatus().SetError(-1, DNBError::Generic);
135324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (err_str[0])
135424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            ctx.LaunchStatus().SetErrorString(err_str);
1355643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                        RNBLogSTDERR ("error: failed to attach to process named: \"%s\" %s\n", waitfor_pid_name.c_str(), err_str);
135624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        mode = eRNBRunLoopModeExit;
135724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
135824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else
135924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
136024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        ctx.SetProcessID(pid);
136124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        mode = eRNBRunLoopModeInferiorExecuting;
136224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
136324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
136424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else if (attach_pid != INVALID_NUB_PROCESS)
136524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
136624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
136724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    RNBLogSTDOUT ("Attaching to process %i...\n", attach_pid);
136824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    nub_process_t attached_pid;
136972e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                    mode = RNBRunLoopLaunchAttaching (remote, attach_pid, attached_pid);
137024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (mode != eRNBRunLoopModeInferiorExecuting)
137124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
137224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        const char *error_str = remote->Context().LaunchStatus().AsString();
137324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        RNBLogSTDERR ("error: failed to attach process %i: %s\n", attach_pid, error_str ? error_str : "unknown error.");
137424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        mode = eRNBRunLoopModeExit;
137524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
137624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
137724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else if (!attach_pid_name.empty ())
137824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
137924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    struct timespec attach_timeout_abstime, *timeout_ptr = NULL;
138024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (waitfor_duration != 0)
138124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
138224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, 0);
138324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        timeout_ptr = &attach_timeout_abstime;
138424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
138524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1386643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                    RNBLogSTDOUT ("Attaching to process %s...\n", attach_pid_name.c_str());
138724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    nub_process_t pid = DNBProcessAttachByName (attach_pid_name.c_str(), timeout_ptr, err_str, sizeof(err_str));
138824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    g_pid = pid;
138924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (pid == INVALID_NUB_PROCESS)
139024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
139124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        ctx.LaunchStatus().SetError(-1, DNBError::Generic);
139224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (err_str[0])
139324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            ctx.LaunchStatus().SetErrorString(err_str);
1394643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                        RNBLogSTDERR ("error: failed to attach to process named: \"%s\" %s\n", waitfor_pid_name.c_str(), err_str);
139524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        mode = eRNBRunLoopModeExit;
139624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
139724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else
139824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
139924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        ctx.SetProcessID(pid);
140024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        mode = eRNBRunLoopModeInferiorExecuting;
140124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
140224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
140324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
140424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
140524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
1406643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                    RNBLogSTDERR ("error: asked to attach with empty name and invalid PID.\n");
140724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    mode = eRNBRunLoopModeExit;
140824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
140924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
141024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (mode != eRNBRunLoopModeExit)
141124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
141224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (listen_port != INT32_MAX)
141324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
1414a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton                        if (!StartListening (remote, listen_host.c_str(), listen_port, unix_socket_name.c_str()))
141524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            mode = eRNBRunLoopModeExit;
141624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
141724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    else if (str[0] == '/')
141824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
141972e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        if (remote->Comm().OpenFile (str))
142024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            mode = eRNBRunLoopModeExit;
142124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
142224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (mode != eRNBRunLoopModeExit)
1423643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                        RNBLogSTDOUT ("Waiting for debugger instructions for process %d.\n", attach_pid);
142424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
142524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
142624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
142724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case eRNBRunLoopModeInferiorLaunching:
142824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
142972e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                    mode = RNBRunLoopLaunchInferior (remote,
1430a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                                                     ctx.GetSTDINPath(),
1431a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                                                     ctx.GetSTDOUTPath(),
1432a2f7423310044cf76d8d52aa9153b7fd8b226b49Greg Clayton                                                     ctx.GetSTDERRPath(),
143372e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                                                     no_stdio);
143472e1c782ba1e4226da37af4722af608de9f39408Greg Clayton
143572e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                    if (mode == eRNBRunLoopModeInferiorExecuting)
143624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
143772e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        if (listen_port != INT32_MAX)
143872e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        {
1439a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton                            if (!StartListening (remote, listen_host.c_str(), listen_port, unix_socket_name.c_str()))
144072e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                                mode = eRNBRunLoopModeExit;
144172e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        }
144272e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        else if (str[0] == '/')
144372e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        {
144472e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                            if (remote->Comm().OpenFile (str))
144572e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                                mode = eRNBRunLoopModeExit;
144672e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        }
144772e1c782ba1e4226da37af4722af608de9f39408Greg Clayton
144872e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        if (mode != eRNBRunLoopModeExit)
1449643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham                            RNBLogSTDOUT ("Got a connection, launched process %s.\n", argv_sub_zero);
145024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
145172e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                    else
145224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
145372e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                        const char *error_str = remote->Context().LaunchStatus().AsString();
14543646e6812b42737c578b99a57f686ae9de279cceJason Molenda                        RNBLogSTDERR ("error: failed to launch process %s: %s\n", argv_sub_zero, error_str ? error_str : "unknown error.");
145524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
145624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
145724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
145824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
145924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case eRNBRunLoopModeInferiorExecuting:
146072e1c782ba1e4226da37af4722af608de9f39408Greg Clayton                mode = RNBRunLoopInferiorExecuting(remote);
146124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
146224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
14634fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            case eRNBRunLoopModePlatformMode:
14644fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                if (listen_port != INT32_MAX)
14654fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                {
1466a619e8ec81ff9c838285105c034ee70a290be904Greg Clayton                    if (!StartListening (remote, listen_host.c_str(), listen_port, unix_socket_name.c_str()))
14674fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                        mode = eRNBRunLoopModeExit;
14684fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                }
14694fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                else if (str[0] == '/')
14704fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                {
14714fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                    if (remote->Comm().OpenFile (str))
14724fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                        mode = eRNBRunLoopModeExit;
14734fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                }
14744fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton
14754fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                if (mode != eRNBRunLoopModeExit)
14764fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                    mode = RNBRunLoopPlatform (remote);
14774fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton                break;
14784fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton
147924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            default:
148024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                mode = eRNBRunLoopModeExit;
148124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            case eRNBRunLoopModeExit:
148224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                break;
148324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
148424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
148524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
148672e1c782ba1e4226da37af4722af608de9f39408Greg Clayton    remote->StopReadRemoteDataThread ();
148772e1c782ba1e4226da37af4722af608de9f39408Greg Clayton    remote->Context().SetProcessID(INVALID_NUB_PROCESS);
1488643adf8a3e1b5056fa2eedcc1b8bebbb1791dd9bJim Ingham    RNBLogSTDOUT ("Exiting.\n");
148924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
149024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return 0;
149124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
1492