diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 | 
| commit | 14f1b3e8826ce43b978db93a62d1166055db5394 (patch) | |
| tree | 0a00ad8d3498783fe0193f3b656bca17c4c8697d /tools/debugserver/source/debugserver.cpp | |
| parent | 4ee8c119c71a06dcad1e0fecc8c675e480e59337 (diff) | |
Notes
Diffstat (limited to 'tools/debugserver/source/debugserver.cpp')
| -rw-r--r-- | tools/debugserver/source/debugserver.cpp | 2877 | 
1 files changed, 1436 insertions, 1441 deletions
| diff --git a/tools/debugserver/source/debugserver.cpp b/tools/debugserver/source/debugserver.cpp index a22f046771d9..0cb72f4ece45 100644 --- a/tools/debugserver/source/debugserver.cpp +++ b/tools/debugserver/source/debugserver.cpp @@ -7,38 +7,40 @@  //  //===----------------------------------------------------------------------===// -#include <sys/socket.h> -#include <sys/types.h> +#include <arpa/inet.h> +#include <asl.h> +#include <crt_externs.h> // for _NSGetEnviron()  #include <errno.h>  #include <getopt.h> -#include <netinet/in.h> -#include <sys/select.h> -#include <sys/sysctl.h> -#include <string> -#include <vector> -#include <asl.h> -#include <arpa/inet.h>  #include <netdb.h>  #include <netinet/in.h> +#include <netinet/in.h>  #include <netinet/tcp.h> -#include <sys/un.h> +#include <string> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/sysctl.h>  #include <sys/types.h> -#include <crt_externs.h> // for _NSGetEnviron() +#include <sys/types.h> +#include <sys/un.h> +#include <vector> -#if defined (__APPLE__) +#if defined(__APPLE__)  #include <sched.h> -extern "C" int proc_set_wakemon_params(pid_t, int, int); // <libproc_internal.h> SPI +extern "C" int proc_set_wakemon_params(pid_t, int, +                                       int); // <libproc_internal.h> SPI  #endif  #include "CFString.h"  #include "DNB.h"  #include "DNBLog.h"  #include "DNBTimer.h" +#include "OsLogger.h"  #include "PseudoTerminal.h"  #include "RNBContext.h" +#include "RNBRemote.h"  #include "RNBServices.h"  #include "RNBSocket.h" -#include "RNBRemote.h"  #include "SysSignal.h"  // Global PID in case we get a signal and need to stop the process... @@ -47,23 +49,21 @@ nub_process_t g_pid = INVALID_NUB_PROCESS;  //----------------------------------------------------------------------  // Run loop modes which determine which run loop function will be called  //---------------------------------------------------------------------- -typedef enum -{ -    eRNBRunLoopModeInvalid = 0, -    eRNBRunLoopModeGetStartModeFromRemoteProtocol, -    eRNBRunLoopModeInferiorAttaching, -    eRNBRunLoopModeInferiorLaunching, -    eRNBRunLoopModeInferiorExecuting, -    eRNBRunLoopModePlatformMode, -    eRNBRunLoopModeExit +typedef enum { +  eRNBRunLoopModeInvalid = 0, +  eRNBRunLoopModeGetStartModeFromRemoteProtocol, +  eRNBRunLoopModeInferiorAttaching, +  eRNBRunLoopModeInferiorLaunching, +  eRNBRunLoopModeInferiorExecuting, +  eRNBRunLoopModePlatformMode, +  eRNBRunLoopModeExit  } RNBRunLoopMode; -  //----------------------------------------------------------------------  // Global Variables  //----------------------------------------------------------------------  RNBRemoteSP g_remoteSP; -static int g_lockdown_opt  = 0; +static int g_lockdown_opt = 0;  static int g_applist_opt = 0;  static nub_launch_flavor_t g_launch_flavor = eLaunchFlavorDefault;  int g_disable_aslr = 0; @@ -71,8 +71,22 @@ int g_disable_aslr = 0;  int g_isatty = 0;  bool g_detach_on_error = true; -#define RNBLogSTDOUT(fmt, ...) do { if (g_isatty) { fprintf(stdout, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0) -#define RNBLogSTDERR(fmt, ...) do { if (g_isatty) { fprintf(stderr, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0) +#define RNBLogSTDOUT(fmt, ...)                                                 \ +  do {                                                                         \ +    if (g_isatty) {                                                            \ +      fprintf(stdout, fmt, ##__VA_ARGS__);                                     \ +    } else {                                                                   \ +      _DNBLog(0, fmt, ##__VA_ARGS__);                                          \ +    }                                                                          \ +  } while (0) +#define RNBLogSTDERR(fmt, ...)                                                 \ +  do {                                                                         \ +    if (g_isatty) {                                                            \ +      fprintf(stderr, fmt, ##__VA_ARGS__);                                     \ +    } else {                                                                   \ +      _DNBLog(0, fmt, ##__VA_ARGS__);                                          \ +    }                                                                          \ +  } while (0)  //----------------------------------------------------------------------  // Get our program path and arguments from the remote connection. @@ -80,306 +94,290 @@ bool g_detach_on_error = true;  // arguments, wait for the new process to finish launching and hit its  // entry point,  and then return the run loop mode that should come next.  //---------------------------------------------------------------------- -RNBRunLoopMode -RNBRunLoopGetStartModeFromRemote (RNBRemote* remote) -{ -    std::string packet; - -    if (remote) -    { -        RNBContext& ctx = remote->Context(); -        uint32_t event_mask = RNBContext::event_read_packet_available | -                              RNBContext::event_read_thread_exiting; - -        // Spin waiting to get the A packet. -        while (1) -        { -            DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...",__FUNCTION__, event_mask); -            nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); -            DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", __FUNCTION__, event_mask, set_events); - -            if (set_events & RNBContext::event_read_thread_exiting) -            { -                RNBLogSTDERR ("error: packet read thread exited.\n"); -                return eRNBRunLoopModeExit; -            } +RNBRunLoopMode RNBRunLoopGetStartModeFromRemote(RNBRemote *remote) { +  std::string packet; + +  if (remote) { +    RNBContext &ctx = remote->Context(); +    uint32_t event_mask = RNBContext::event_read_packet_available | +                          RNBContext::event_read_thread_exiting; + +    // Spin waiting to get the A packet. +    while (1) { +      DNBLogThreadedIf(LOG_RNB_MAX, +                       "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...", +                       __FUNCTION__, event_mask); +      nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); +      DNBLogThreadedIf(LOG_RNB_MAX, +                       "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", +                       __FUNCTION__, event_mask, set_events); + +      if (set_events & RNBContext::event_read_thread_exiting) { +        RNBLogSTDERR("error: packet read thread exited.\n"); +        return eRNBRunLoopModeExit; +      } -            if (set_events & RNBContext::event_read_packet_available) -            { -                rnb_err_t err = rnb_err; -                RNBRemote::PacketEnum type; - -                err = remote->HandleReceivedPacket (&type); - -                // check if we tried to attach to a process -                if (type == RNBRemote::vattach || type == RNBRemote::vattachwait || type == RNBRemote::vattachorwait) -                { -                    if (err == rnb_success) -                    { -                        RNBLogSTDOUT ("Attach succeeded, ready to debug.\n"); -                        return eRNBRunLoopModeInferiorExecuting; -                    } -                    else -                    { -                        RNBLogSTDERR ("error: attach failed.\n"); -                        return eRNBRunLoopModeExit; -                    } -                } - -                if (err == rnb_success) -                { -                    // If we got our arguments we are ready to launch using the arguments -                    // and any environment variables we received. -                    if (type == RNBRemote::set_argv) -                    { -                        return eRNBRunLoopModeInferiorLaunching; -                    } -                } -                else if (err == rnb_not_connected) -                { -                    RNBLogSTDERR ("error: connection lost.\n"); -                    return eRNBRunLoopModeExit; -                } -                else -                { -                    // a catch all for any other gdb remote packets that failed -                    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Error getting packet.",__FUNCTION__); -                    continue; -                } - -                DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); -            } -            else -            { -                DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Connection closed before getting \"A\" packet.", __FUNCTION__); -                return eRNBRunLoopModeExit; -            } +      if (set_events & RNBContext::event_read_packet_available) { +        rnb_err_t err = rnb_err; +        RNBRemote::PacketEnum type; + +        err = remote->HandleReceivedPacket(&type); + +        // check if we tried to attach to a process +        if (type == RNBRemote::vattach || type == RNBRemote::vattachwait || +            type == RNBRemote::vattachorwait) { +          if (err == rnb_success) { +            RNBLogSTDOUT("Attach succeeded, ready to debug.\n"); +            return eRNBRunLoopModeInferiorExecuting; +          } else { +            RNBLogSTDERR("error: attach failed.\n"); +            return eRNBRunLoopModeExit; +          } +        } + +        if (err == rnb_success) { +          // If we got our arguments we are ready to launch using the arguments +          // and any environment variables we received. +          if (type == RNBRemote::set_argv) { +            return eRNBRunLoopModeInferiorLaunching; +          } +        } else if (err == rnb_not_connected) { +          RNBLogSTDERR("error: connection lost.\n"); +          return eRNBRunLoopModeExit; +        } else { +          // a catch all for any other gdb remote packets that failed +          DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Error getting packet.", +                           __FUNCTION__); +          continue;          } + +        DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); +      } else { +        DNBLogThreadedIf(LOG_RNB_MINIMAL, +                         "%s Connection closed before getting \"A\" packet.", +                         __FUNCTION__); +        return eRNBRunLoopModeExit; +      }      } -    return eRNBRunLoopModeExit; +  } +  return eRNBRunLoopModeExit;  } -  //----------------------------------------------------------------------  // This run loop mode will wait for the process to launch and hit its  // entry point. It will currently ignore all events except for the  // process state changed event, where it watches for the process stopped  // or crash process state.  //---------------------------------------------------------------------- -RNBRunLoopMode -RNBRunLoopLaunchInferior (RNBRemote *remote, const char *stdin_path, const char *stdout_path, const char *stderr_path, bool no_stdio) -{ -    RNBContext& ctx = remote->Context(); +RNBRunLoopMode RNBRunLoopLaunchInferior(RNBRemote *remote, +                                        const char *stdin_path, +                                        const char *stdout_path, +                                        const char *stderr_path, +                                        bool no_stdio) { +  RNBContext &ctx = remote->Context(); -    // The Process stuff takes a c array, the RNBContext has a vector... -    // So make up a c array. +  // The Process stuff takes a c array, the RNBContext has a vector... +  // So make up a c array. -    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Launching '%s'...", __FUNCTION__, ctx.ArgumentAtIndex(0)); +  DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Launching '%s'...", __FUNCTION__, +                   ctx.ArgumentAtIndex(0)); -    size_t inferior_argc = ctx.ArgumentCount(); -    // Initialize inferior_argv with inferior_argc + 1 NULLs -    std::vector<const char *> inferior_argv(inferior_argc + 1, NULL); +  size_t inferior_argc = ctx.ArgumentCount(); +  // Initialize inferior_argv with inferior_argc + 1 NULLs +  std::vector<const char *> inferior_argv(inferior_argc + 1, NULL); -    size_t i; -    for (i = 0; i < inferior_argc; i++) -        inferior_argv[i] = ctx.ArgumentAtIndex(i); +  size_t i; +  for (i = 0; i < inferior_argc; i++) +    inferior_argv[i] = ctx.ArgumentAtIndex(i); -    // Pass the environment array the same way: +  // Pass the environment array the same way: -    size_t inferior_envc = ctx.EnvironmentCount(); -    // Initialize inferior_argv with inferior_argc + 1 NULLs -    std::vector<const char *> inferior_envp(inferior_envc + 1, NULL); +  size_t inferior_envc = ctx.EnvironmentCount(); +  // Initialize inferior_argv with inferior_argc + 1 NULLs +  std::vector<const char *> inferior_envp(inferior_envc + 1, NULL); -    for (i = 0; i < inferior_envc; i++) -        inferior_envp[i] = ctx.EnvironmentAtIndex(i); +  for (i = 0; i < inferior_envc; i++) +    inferior_envp[i] = ctx.EnvironmentAtIndex(i); -    // Our launch type hasn't been set to anything concrete, so we need to -    // figure our how we are going to launch automatically. +  // Our launch type hasn't been set to anything concrete, so we need to +  // figure our how we are going to launch automatically. -    nub_launch_flavor_t launch_flavor = g_launch_flavor; -    if (launch_flavor == eLaunchFlavorDefault) -    { -        // Our default launch method is posix spawn -        launch_flavor = eLaunchFlavorPosixSpawn; +  nub_launch_flavor_t launch_flavor = g_launch_flavor; +  if (launch_flavor == eLaunchFlavorDefault) { +    // Our default launch method is posix spawn +    launch_flavor = eLaunchFlavorPosixSpawn;  #if defined WITH_FBS -        // Check if we have an app bundle, if so launch using BackBoard Services. -        if (strstr(inferior_argv[0], ".app")) -        { -            launch_flavor = eLaunchFlavorFBS; -        } -#elif defined WITH_BKS -        // Check if we have an app bundle, if so launch using BackBoard Services. -        if (strstr(inferior_argv[0], ".app")) -        { -            launch_flavor = eLaunchFlavorBKS; -        } -#elif defined WITH_SPRINGBOARD -        // Check if we have an app bundle, if so launch using SpringBoard. -        if (strstr(inferior_argv[0], ".app")) -        { -            launch_flavor = eLaunchFlavorSpringBoard; -        } -#endif +    // Check if we have an app bundle, if so launch using BackBoard Services. +    if (strstr(inferior_argv[0], ".app")) { +      launch_flavor = eLaunchFlavorFBS;      } - -    ctx.SetLaunchFlavor(launch_flavor); -    char resolved_path[PATH_MAX]; - -    // If we fail to resolve the path to our executable, then just use what we -    // were given and hope for the best -    if ( !DNBResolveExecutablePath (inferior_argv[0], resolved_path, sizeof(resolved_path)) ) -        ::strncpy(resolved_path, inferior_argv[0], sizeof(resolved_path)); - -    char launch_err_str[PATH_MAX]; -    launch_err_str[0] = '\0'; -    const char * cwd = (ctx.GetWorkingDirPath() != NULL ? ctx.GetWorkingDirPath() -                                                        : ctx.GetWorkingDirectory()); -    const char *process_event = ctx.GetProcessEvent(); -    nub_process_t pid = DNBProcessLaunch (resolved_path, -                                          &inferior_argv[0], -                                          &inferior_envp[0], -                                          cwd, -                                          stdin_path, -                                          stdout_path, -                                          stderr_path, -                                          no_stdio, -                                          launch_flavor, -                                          g_disable_aslr, -                                          process_event, -                                          launch_err_str, -                                          sizeof(launch_err_str)); - -    g_pid = pid; - -    if (pid == INVALID_NUB_PROCESS && strlen (launch_err_str) > 0) -    { -        DNBLogThreaded ("%s DNBProcessLaunch() returned error: '%s'", __FUNCTION__, launch_err_str); -        ctx.LaunchStatus().SetError(-1, DNBError::Generic); -        ctx.LaunchStatus().SetErrorString(launch_err_str); +#elif defined WITH_BKS +    // Check if we have an app bundle, if so launch using BackBoard Services. +    if (strstr(inferior_argv[0], ".app")) { +      launch_flavor = eLaunchFlavorBKS;      } -    else if (pid == INVALID_NUB_PROCESS) -    { -        DNBLogThreaded ("%s DNBProcessLaunch() failed to launch process, unknown failure", __FUNCTION__); -        ctx.LaunchStatus().SetError(-1, DNBError::Generic); -        ctx.LaunchStatus().SetErrorString("<unknown failure>"); +#elif defined WITH_SPRINGBOARD +    // Check if we have an app bundle, if so launch using SpringBoard. +    if (strstr(inferior_argv[0], ".app")) { +      launch_flavor = eLaunchFlavorSpringBoard;      } -    else -    { -        ctx.LaunchStatus().Clear(); +#endif +  } + +  ctx.SetLaunchFlavor(launch_flavor); +  char resolved_path[PATH_MAX]; + +  // If we fail to resolve the path to our executable, then just use what we +  // were given and hope for the best +  if (!DNBResolveExecutablePath(inferior_argv[0], resolved_path, +                                sizeof(resolved_path))) +    ::strncpy(resolved_path, inferior_argv[0], sizeof(resolved_path)); + +  char launch_err_str[PATH_MAX]; +  launch_err_str[0] = '\0'; +  const char *cwd = +      (ctx.GetWorkingDirPath() != NULL ? ctx.GetWorkingDirPath() +                                       : ctx.GetWorkingDirectory()); +  const char *process_event = ctx.GetProcessEvent(); +  nub_process_t pid = DNBProcessLaunch( +      resolved_path, &inferior_argv[0], &inferior_envp[0], cwd, stdin_path, +      stdout_path, stderr_path, no_stdio, launch_flavor, g_disable_aslr, +      process_event, launch_err_str, sizeof(launch_err_str)); + +  g_pid = pid; + +  if (pid == INVALID_NUB_PROCESS && strlen(launch_err_str) > 0) { +    DNBLogThreaded("%s DNBProcessLaunch() returned error: '%s'", __FUNCTION__, +                   launch_err_str); +    ctx.LaunchStatus().SetError(-1, DNBError::Generic); +    ctx.LaunchStatus().SetErrorString(launch_err_str); +  } else if (pid == INVALID_NUB_PROCESS) { +    DNBLogThreaded( +        "%s DNBProcessLaunch() failed to launch process, unknown failure", +        __FUNCTION__); +    ctx.LaunchStatus().SetError(-1, DNBError::Generic); +    ctx.LaunchStatus().SetErrorString("<unknown failure>"); +  } else { +    ctx.LaunchStatus().Clear(); +  } + +  if (remote->Comm().IsConnected()) { +    // It we are connected already, the next thing gdb will do is ask +    // whether the launch succeeded, and if not, whether there is an +    // error code.  So we need to fetch one packet from gdb before we wait +    // on the stop from the target. + +    uint32_t event_mask = RNBContext::event_read_packet_available; +    nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); + +    if (set_events & RNBContext::event_read_packet_available) { +      rnb_err_t err = rnb_err; +      RNBRemote::PacketEnum type; + +      err = remote->HandleReceivedPacket(&type); + +      if (err != rnb_success) { +        DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Error getting packet.", +                         __FUNCTION__); +        return eRNBRunLoopModeExit; +      } +      if (type != RNBRemote::query_launch_success) { +        DNBLogThreadedIf(LOG_RNB_MINIMAL, +                         "%s Didn't get the expected qLaunchSuccess packet.", +                         __FUNCTION__); +      }      } +  } + +  while (pid != INVALID_NUB_PROCESS) { +    // Wait for process to start up and hit entry point +    DNBLogThreadedIf(LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, " +                                     "eEventProcessRunningStateChanged | " +                                     "eEventProcessStoppedStateChanged, true, " +                                     "INFINITE)...", +                     __FUNCTION__, pid); +    nub_event_t set_events = +        DNBProcessWaitForEvents(pid, eEventProcessRunningStateChanged | +                                         eEventProcessStoppedStateChanged, +                                true, NULL); +    DNBLogThreadedIf(LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, " +                                     "eEventProcessRunningStateChanged | " +                                     "eEventProcessStoppedStateChanged, true, " +                                     "INFINITE) => 0x%8.8x", +                     __FUNCTION__, pid, set_events); + +    if (set_events == 0) { +      pid = INVALID_NUB_PROCESS; +      g_pid = pid; +    } else { +      if (set_events & (eEventProcessRunningStateChanged | +                        eEventProcessStoppedStateChanged)) { +        nub_state_t pid_state = DNBProcessGetState(pid); +        DNBLogThreadedIf( +            LOG_RNB_EVENTS, +            "%s process %4.4x state changed (eEventProcessStateChanged): %s", +            __FUNCTION__, pid, DNBStateAsString(pid_state)); + +        switch (pid_state) { +        case eStateInvalid: +        case eStateUnloaded: +        case eStateAttaching: +        case eStateLaunching: +        case eStateSuspended: +          break; // Ignore -    if (remote->Comm().IsConnected()) -    { -        // It we are connected already, the next thing gdb will do is ask -        // whether the launch succeeded, and if not, whether there is an -        // error code.  So we need to fetch one packet from gdb before we wait -        // on the stop from the target. - -        uint32_t event_mask = RNBContext::event_read_packet_available; -        nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - -        if (set_events & RNBContext::event_read_packet_available) -        { -            rnb_err_t err = rnb_err; -            RNBRemote::PacketEnum type; - -            err = remote->HandleReceivedPacket (&type); +        case eStateRunning: +        case eStateStepping: +          // Still waiting to stop at entry point... +          break; -            if (err != rnb_success) -            { -                DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Error getting packet.", __FUNCTION__); -                return eRNBRunLoopModeExit; -            } -            if (type != RNBRemote::query_launch_success) -            { -                DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Didn't get the expected qLaunchSuccess packet.", __FUNCTION__); -            } -        } -    } +        case eStateStopped: +        case eStateCrashed: +          ctx.SetProcessID(pid); +          return eRNBRunLoopModeInferiorExecuting; -    while (pid != INVALID_NUB_PROCESS) -    { -        // Wait for process to start up and hit entry point -        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...", __FUNCTION__, pid); -        nub_event_t set_events = DNBProcessWaitForEvents (pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, NULL); -        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x", __FUNCTION__, pid, set_events); - -        if (set_events == 0) -        { -            pid = INVALID_NUB_PROCESS; -            g_pid = pid; +        case eStateDetached: +        case eStateExited: +          pid = INVALID_NUB_PROCESS; +          g_pid = pid; +          return eRNBRunLoopModeExit;          } -        else -        { -            if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged)) -            { -                nub_state_t pid_state = DNBProcessGetState (pid); -                DNBLogThreadedIf (LOG_RNB_EVENTS, "%s process %4.4x state changed (eEventProcessStateChanged): %s", __FUNCTION__, pid, DNBStateAsString(pid_state)); - -                switch (pid_state) -                { -                    case eStateInvalid: -                    case eStateUnloaded: -                    case eStateAttaching: -                    case eStateLaunching: -                    case eStateSuspended: -                        break;  // Ignore - -                    case eStateRunning: -                    case eStateStepping: -                        // Still waiting to stop at entry point... -                        break; - -                    case eStateStopped: -                    case eStateCrashed: -                        ctx.SetProcessID(pid); -                        return eRNBRunLoopModeInferiorExecuting; - -                    case eStateDetached: -                    case eStateExited: -                        pid = INVALID_NUB_PROCESS; -                        g_pid = pid; -                        return eRNBRunLoopModeExit; -                } -            } +      } -            DNBProcessResetEvents(pid, set_events); -        } +      DNBProcessResetEvents(pid, set_events);      } +  } -    return eRNBRunLoopModeExit; +  return eRNBRunLoopModeExit;  } -  //----------------------------------------------------------------------  // This run loop mode will wait for the process to launch and hit its  // entry point. It will currently ignore all events except for the  // process state changed event, where it watches for the process stopped  // or crash process state.  //---------------------------------------------------------------------- -RNBRunLoopMode -RNBRunLoopLaunchAttaching (RNBRemote *remote, nub_process_t attach_pid, nub_process_t& pid) -{ -    RNBContext& ctx = remote->Context(); - -    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__, attach_pid); -    char err_str[1024]; -    pid = DNBProcessAttach (attach_pid, NULL, err_str, sizeof(err_str)); -    g_pid = pid; - -    if (pid == INVALID_NUB_PROCESS) -    { -        ctx.LaunchStatus().SetError(-1, DNBError::Generic); -        if (err_str[0]) -            ctx.LaunchStatus().SetErrorString(err_str); -        return eRNBRunLoopModeExit; -    } -    else -    { -        ctx.SetProcessID(pid); -        return eRNBRunLoopModeInferiorExecuting; -    } +RNBRunLoopMode RNBRunLoopLaunchAttaching(RNBRemote *remote, +                                         nub_process_t attach_pid, +                                         nub_process_t &pid) { +  RNBContext &ctx = remote->Context(); + +  DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__, +                   attach_pid); +  char err_str[1024]; +  pid = DNBProcessAttach(attach_pid, NULL, err_str, sizeof(err_str)); +  g_pid = pid; + +  if (pid == INVALID_NUB_PROCESS) { +    ctx.LaunchStatus().SetError(-1, DNBError::Generic); +    if (err_str[0]) +      ctx.LaunchStatus().SetErrorString(err_str); +    return eRNBRunLoopModeExit; +  } else { +    ctx.SetProcessID(pid); +    return eRNBRunLoopModeInferiorExecuting; +  }  }  //---------------------------------------------------------------------- @@ -389,276 +387,271 @@ RNBRunLoopLaunchAttaching (RNBRemote *remote, nub_process_t attach_pid, nub_proc  //----------------------------------------------------------------------  int g_sigint_received = 0;  int g_sigpipe_received = 0; -void -signal_handler(int signo) -{ -    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (%s)", __FUNCTION__, SysSignal::Name(signo)); - -    switch (signo) -    { -        case SIGINT: -            g_sigint_received++; -            if (g_pid != INVALID_NUB_PROCESS) -            { -                // Only send a SIGINT once... -                if (g_sigint_received == 1) -                { -                    switch (DNBProcessGetState (g_pid)) -                    { -                        case eStateRunning: -                        case eStateStepping: -                            DNBProcessSignal (g_pid, SIGSTOP); -                            return; -                        default: -                            break; -                    } -                } -            } -            exit (SIGINT); -            break; - -        case SIGPIPE: -            g_sigpipe_received = 1; -            break; +void signal_handler(int signo) { +  DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s (%s)", __FUNCTION__, +                   SysSignal::Name(signo)); + +  switch (signo) { +  case SIGINT: +    g_sigint_received++; +    if (g_pid != INVALID_NUB_PROCESS) { +      // Only send a SIGINT once... +      if (g_sigint_received == 1) { +        switch (DNBProcessGetState(g_pid)) { +        case eStateRunning: +        case eStateStepping: +          DNBProcessSignal(g_pid, SIGSTOP); +          return; +        default: +          break; +        } +      }      } +    exit(SIGINT); +    break; + +  case SIGPIPE: +    g_sigpipe_received = 1; +    break; +  }  }  // Return the new run loop mode based off of the current process state -RNBRunLoopMode -HandleProcessStateChange (RNBRemote *remote, bool initialize) -{ -    RNBContext& ctx = remote->Context(); -    nub_process_t pid = ctx.ProcessID(); - -    if (pid == INVALID_NUB_PROCESS) -    { -        DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s error: pid invalid, exiting...", __FUNCTION__); -        return eRNBRunLoopModeExit; -    } -    nub_state_t pid_state = DNBProcessGetState (pid); - -    DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i)  pid_state = %s", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state)); - -    switch (pid_state) -    { -        case eStateInvalid: -        case eStateUnloaded: -            // Something bad happened -            return eRNBRunLoopModeExit; -            break; - -        case eStateAttaching: -        case eStateLaunching: -            return eRNBRunLoopModeInferiorExecuting; - -        case eStateSuspended: -        case eStateCrashed: -        case eStateStopped: -            // If we stop due to a signal, so clear the fact that we got a SIGINT -            // so we can stop ourselves again (but only while our inferior -            // process is running..) -            g_sigint_received = 0; -            if (initialize == false) -            { -                // Compare the last stop count to our current notion of a stop count -                // to make sure we don't notify more than once for a given stop. -                nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount(); -                bool pid_stop_count_changed = ctx.SetProcessStopCount(DNBProcessGetStopCount(pid)); -                if (pid_stop_count_changed) -                { -                    remote->FlushSTDIO(); - -                    if (ctx.GetProcessStopCount() == 1) -                    { -                        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); -                    } -                    else -                    { - -                        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); -                        remote->NotifyThatProcessStopped (); -                    } -                } -                else -                { -                    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); -                } -            } -            return eRNBRunLoopModeInferiorExecuting; +RNBRunLoopMode HandleProcessStateChange(RNBRemote *remote, bool initialize) { +  RNBContext &ctx = remote->Context(); +  nub_process_t pid = ctx.ProcessID(); -        case eStateStepping: -        case eStateRunning: -            return eRNBRunLoopModeInferiorExecuting; +  if (pid == INVALID_NUB_PROCESS) { +    DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s error: pid invalid, exiting...", +                     __FUNCTION__); +    return eRNBRunLoopModeExit; +  } +  nub_state_t pid_state = DNBProcessGetState(pid); -        case eStateExited: -            remote->HandlePacket_last_signal(NULL); -        case eStateDetached: -            return eRNBRunLoopModeExit; +  DNBLogThreadedIf(LOG_RNB_MINIMAL, +                   "%s (&remote, initialize=%i)  pid_state = %s", __FUNCTION__, +                   (int)initialize, DNBStateAsString(pid_state)); +  switch (pid_state) { +  case eStateInvalid: +  case eStateUnloaded: +    // Something bad happened +    return eRNBRunLoopModeExit; +    break; + +  case eStateAttaching: +  case eStateLaunching: +    return eRNBRunLoopModeInferiorExecuting; + +  case eStateSuspended: +  case eStateCrashed: +  case eStateStopped: +    // If we stop due to a signal, so clear the fact that we got a SIGINT +    // so we can stop ourselves again (but only while our inferior +    // process is running..) +    g_sigint_received = 0; +    if (initialize == false) { +      // Compare the last stop count to our current notion of a stop count +      // to make sure we don't notify more than once for a given stop. +      nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount(); +      bool pid_stop_count_changed = +          ctx.SetProcessStopCount(DNBProcessGetStopCount(pid)); +      if (pid_stop_count_changed) { +        remote->FlushSTDIO(); + +        if (ctx.GetProcessStopCount() == 1) { +          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); +        } else { + +          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); +          remote->NotifyThatProcessStopped(); +        } +      } else { +        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); +      }      } +    return eRNBRunLoopModeInferiorExecuting; -    // Catch all... +  case eStateStepping: +  case eStateRunning: +    return eRNBRunLoopModeInferiorExecuting; + +  case eStateExited: +    remote->HandlePacket_last_signal(NULL); +  case eStateDetached:      return eRNBRunLoopModeExit; +  } + +  // Catch all... +  return eRNBRunLoopModeExit;  }  // This function handles the case where our inferior program is stopped and  // we are waiting for gdb remote protocol packets. When a packet occurs that  // makes the inferior run, we need to leave this function with a new state  // as the return code. -RNBRunLoopMode -RNBRunLoopInferiorExecuting (RNBRemote *remote) -{ -    DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); -    RNBContext& ctx = remote->Context(); - -    // Init our mode and set 'is_running' based on the current process state -    RNBRunLoopMode mode = HandleProcessStateChange (remote, true); - -    while (ctx.ProcessID() != INVALID_NUB_PROCESS) -    { - -        std::string set_events_str; -        uint32_t event_mask = ctx.NormalEventBits(); - -        if (!ctx.ProcessStateRunning()) -        { -            // Clear some bits if we are not running so we don't send any async packets -            event_mask &= ~RNBContext::event_proc_stdio_available; -            event_mask &= ~RNBContext::event_proc_profile_data; -        } - -        // We want to make sure we consume all process state changes and have -        // whomever is notifying us to wait for us to reset the event bit before -        // continuing. -        //ctx.Events().SetResetAckMask (RNBContext::event_proc_state_changed); - -        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) ...",__FUNCTION__, event_mask); -        nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); -        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)); - -        if (set_events) -        { -            if ((set_events & RNBContext::event_proc_thread_exiting) || -                (set_events & RNBContext::event_proc_stdio_available)) -            { -                remote->FlushSTDIO(); -            } - -            if (set_events & RNBContext::event_proc_profile_data) -            { -                remote->SendAsyncProfileData(); -            } - -            if (set_events & RNBContext::event_read_packet_available) -            { -                // handleReceivedPacket will take care of resetting the -                // event_read_packet_available events when there are no more... -                set_events ^= RNBContext::event_read_packet_available; - -                if (ctx.ProcessStateRunning()) -                { -                    if (remote->HandleAsyncPacket() == rnb_not_connected) -                    { -                        // TODO: connect again? Exit? -                    } -                } -                else -                { -                    if (remote->HandleReceivedPacket() == rnb_not_connected) -                    { -                        // TODO: connect again? Exit? -                    } -                } -            } - -            if (set_events & RNBContext::event_proc_state_changed) -            { -                mode = HandleProcessStateChange (remote, false); -                ctx.Events().ResetEvents(RNBContext::event_proc_state_changed); -                set_events ^= RNBContext::event_proc_state_changed; -            } +RNBRunLoopMode RNBRunLoopInferiorExecuting(RNBRemote *remote) { +  DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); +  RNBContext &ctx = remote->Context(); + +  // Init our mode and set 'is_running' based on the current process state +  RNBRunLoopMode mode = HandleProcessStateChange(remote, true); + +  while (ctx.ProcessID() != INVALID_NUB_PROCESS) { + +    std::string set_events_str; +    uint32_t event_mask = ctx.NormalEventBits(); + +    if (!ctx.ProcessStateRunning()) { +      // Clear some bits if we are not running so we don't send any async +      // packets +      event_mask &= ~RNBContext::event_proc_stdio_available; +      event_mask &= ~RNBContext::event_proc_profile_data; +      // When we enable async structured data packets over another logical +      // channel, +      // this can be relaxed. +      event_mask &= ~RNBContext::event_darwin_log_data_available; +    } -            if (set_events & RNBContext::event_proc_thread_exiting) -            { -                mode = eRNBRunLoopModeExit; +    // We want to make sure we consume all process state changes and have +    // whomever is notifying us to wait for us to reset the event bit before +    // continuing. +    // ctx.Events().SetResetAckMask (RNBContext::event_proc_state_changed); + +    DNBLogThreadedIf(LOG_RNB_EVENTS, +                     "%s ctx.Events().WaitForSetEvents(0x%08x) ...", +                     __FUNCTION__, event_mask); +    nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); +    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)); + +    if (set_events) { +      if ((set_events & RNBContext::event_proc_thread_exiting) || +          (set_events & RNBContext::event_proc_stdio_available)) { +        remote->FlushSTDIO(); +      } + +      if (set_events & RNBContext::event_proc_profile_data) { +        remote->SendAsyncProfileData(); +      } + +      if (set_events & RNBContext::event_darwin_log_data_available) { +        remote->SendAsyncDarwinLogData(); +      } + +      if (set_events & RNBContext::event_read_packet_available) { +        // handleReceivedPacket will take care of resetting the +        // event_read_packet_available events when there are no more... +        set_events ^= RNBContext::event_read_packet_available; + +        if (ctx.ProcessStateRunning()) { +          if (remote->HandleAsyncPacket() == rnb_not_connected) { +            // TODO: connect again? Exit? +          } +        } else { +          if (remote->HandleReceivedPacket() == rnb_not_connected) { +            // TODO: connect again? Exit? +          } +        } +      } + +      if (set_events & RNBContext::event_proc_state_changed) { +        mode = HandleProcessStateChange(remote, false); +        ctx.Events().ResetEvents(RNBContext::event_proc_state_changed); +        set_events ^= RNBContext::event_proc_state_changed; +      } + +      if (set_events & RNBContext::event_proc_thread_exiting) { +        mode = eRNBRunLoopModeExit; +      } + +      if (set_events & RNBContext::event_read_thread_exiting) { +        // Out remote packet receiving thread exited, exit for now. +        if (ctx.HasValidProcessID()) { +          // TODO: We should add code that will leave the current process +          // in its current state and listen for another connection... +          if (ctx.ProcessStateRunning()) { +            if (ctx.GetDetachOnError()) { +              DNBLog("debugserver's event read thread is exiting, detaching " +                     "from the inferior process."); +              DNBProcessDetach(ctx.ProcessID()); +            } else { +              DNBLog("debugserver's event read thread is exiting, killing the " +                     "inferior process."); +              DNBProcessKill(ctx.ProcessID());              } - -            if (set_events & RNBContext::event_read_thread_exiting) -            { -                // Out remote packet receiving thread exited, exit for now. -                if (ctx.HasValidProcessID()) -                { -                    // TODO: We should add code that will leave the current process -                    // in its current state and listen for another connection... -                    if (ctx.ProcessStateRunning()) -                    { -                        if (ctx.GetDetachOnError()) -                        { -                            DNBLog ("debugserver's event read thread is exiting, detaching from the inferior process."); -                            DNBProcessDetach (ctx.ProcessID()); -                        } -                        else -                        { -                            DNBLog ("debugserver's event read thread is exiting, killing the inferior process."); -                            DNBProcessKill (ctx.ProcessID()); -                        } -                    } -                    else -                    { -                        if (ctx.GetDetachOnError()) -                        { -                            DNBLog ("debugserver's event read thread is exiting, detaching from the inferior process."); -                            DNBProcessDetach (ctx.ProcessID()); -                        } -                    } -                } -                mode = eRNBRunLoopModeExit; +          } else { +            if (ctx.GetDetachOnError()) { +              DNBLog("debugserver's event read thread is exiting, detaching " +                     "from the inferior process."); +              DNBProcessDetach(ctx.ProcessID());              } +          }          } - -        // Reset all event bits that weren't reset for now... -        if (set_events != 0) -            ctx.Events().ResetEvents(set_events); - -        if (mode != eRNBRunLoopModeInferiorExecuting) -            break; +        mode = eRNBRunLoopModeExit; +      }      } -    return mode; -} +    // Reset all event bits that weren't reset for now... +    if (set_events != 0) +      ctx.Events().ResetEvents(set_events); +    if (mode != eRNBRunLoopModeInferiorExecuting) +      break; +  } -RNBRunLoopMode -RNBRunLoopPlatform (RNBRemote *remote) -{ -    RNBRunLoopMode mode = eRNBRunLoopModePlatformMode; -    RNBContext& ctx = remote->Context(); - -    while (mode == eRNBRunLoopModePlatformMode) -    { -        std::string set_events_str; -        const uint32_t event_mask = RNBContext::event_read_packet_available | -                                    RNBContext::event_read_thread_exiting; - -        DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) ...",__FUNCTION__, event_mask); -        nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); -        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)); - -        if (set_events) -        { -            if (set_events & RNBContext::event_read_packet_available) -            { -                if (remote->HandleReceivedPacket() == rnb_not_connected) -                    mode = eRNBRunLoopModeExit; -            } +  return mode; +} -            if (set_events & RNBContext::event_read_thread_exiting) -            { -                mode = eRNBRunLoopModeExit; -            } -            ctx.Events().ResetEvents(set_events); -        } +RNBRunLoopMode RNBRunLoopPlatform(RNBRemote *remote) { +  RNBRunLoopMode mode = eRNBRunLoopModePlatformMode; +  RNBContext &ctx = remote->Context(); + +  while (mode == eRNBRunLoopModePlatformMode) { +    std::string set_events_str; +    const uint32_t event_mask = RNBContext::event_read_packet_available | +                                RNBContext::event_read_thread_exiting; + +    DNBLogThreadedIf(LOG_RNB_EVENTS, +                     "%s ctx.Events().WaitForSetEvents(0x%08x) ...", +                     __FUNCTION__, event_mask); +    nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); +    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)); + +    if (set_events) { +      if (set_events & RNBContext::event_read_packet_available) { +        if (remote->HandleReceivedPacket() == rnb_not_connected) +          mode = eRNBRunLoopModeExit; +      } + +      if (set_events & RNBContext::event_read_thread_exiting) { +        mode = eRNBRunLoopModeExit; +      } +      ctx.Events().ResetEvents(set_events);      } -    return eRNBRunLoopModeExit; +  } +  return eRNBRunLoopModeExit;  }  //---------------------------------------------------------------------- @@ -666,1012 +659,1014 @@ RNBRunLoopPlatform (RNBRemote *remote)  // Returns 1 for success 0 for failure.  //---------------------------------------------------------------------- -static void -PortWasBoundCallbackUnixSocket (const void *baton, in_port_t port) -{ -    //::printf ("PortWasBoundCallbackUnixSocket (baton = %p, port = %u)\n", baton, port); - -    const char *unix_socket_name = (const char *)baton; - -    if (unix_socket_name && unix_socket_name[0]) -    { -        // We were given a unix socket name to use to communicate the port -        // that we ended up binding to back to our parent process -        struct sockaddr_un saddr_un; -        int s = ::socket (AF_UNIX, SOCK_STREAM, 0); -        if (s < 0) -        { -            perror("error: socket (AF_UNIX, SOCK_STREAM, 0)"); -            exit(1); -        } - -        saddr_un.sun_family = AF_UNIX; -        ::strncpy(saddr_un.sun_path, unix_socket_name, sizeof(saddr_un.sun_path) - 1); -        saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; -        saddr_un.sun_len = SUN_LEN (&saddr_un); +static void PortWasBoundCallbackUnixSocket(const void *baton, in_port_t port) { +  //::printf ("PortWasBoundCallbackUnixSocket (baton = %p, port = %u)\n", baton, +  //port); -        if (::connect (s, (struct sockaddr *)&saddr_un, static_cast<socklen_t>(SUN_LEN (&saddr_un))) < 0) -        { -            perror("error: connect (socket, &saddr_un, saddr_un_len)"); -            exit(1); -        } +  const char *unix_socket_name = (const char *)baton; -        //::printf ("connect () sucess!!\n"); +  if (unix_socket_name && unix_socket_name[0]) { +    // We were given a unix socket name to use to communicate the port +    // that we ended up binding to back to our parent process +    struct sockaddr_un saddr_un; +    int s = ::socket(AF_UNIX, SOCK_STREAM, 0); +    if (s < 0) { +      perror("error: socket (AF_UNIX, SOCK_STREAM, 0)"); +      exit(1); +    } +    saddr_un.sun_family = AF_UNIX; +    ::strncpy(saddr_un.sun_path, unix_socket_name, +              sizeof(saddr_un.sun_path) - 1); +    saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; +    saddr_un.sun_len = SUN_LEN(&saddr_un); -        // We were able to connect to the socket, now write our PID so whomever -        // launched us will know this process's ID -        RNBLogSTDOUT ("Listening to port %i...\n", port); +    if (::connect(s, (struct sockaddr *)&saddr_un, +                  static_cast<socklen_t>(SUN_LEN(&saddr_un))) < 0) { +      perror("error: connect (socket, &saddr_un, saddr_un_len)"); +      exit(1); +    } -        char pid_str[64]; -        const int pid_str_len = ::snprintf (pid_str, sizeof(pid_str), "%u", port); -        const ssize_t bytes_sent = ::send (s, pid_str, pid_str_len, 0); +    //::printf ("connect () sucess!!\n"); -        if (pid_str_len != bytes_sent) -        { -            perror("error: send (s, pid_str, pid_str_len, 0)"); -            exit (1); -        } +    // We were able to connect to the socket, now write our PID so whomever +    // launched us will know this process's ID +    RNBLogSTDOUT("Listening to port %i...\n", port); -        //::printf ("send () sucess!!\n"); +    char pid_str[64]; +    const int pid_str_len = ::snprintf(pid_str, sizeof(pid_str), "%u", port); +    const ssize_t bytes_sent = ::send(s, pid_str, pid_str_len, 0); -        // We are done with the socket -        close (s); +    if (pid_str_len != bytes_sent) { +      perror("error: send (s, pid_str, pid_str_len, 0)"); +      exit(1);      } + +    //::printf ("send () sucess!!\n"); + +    // We are done with the socket +    close(s); +  }  } -static void -PortWasBoundCallbackNamedPipe (const void *baton, uint16_t port) -{ -    const char *named_pipe = (const char *)baton; -    if (named_pipe && named_pipe[0]) -    { -        int fd = ::open(named_pipe, O_WRONLY); -        if (fd > -1) -        { -            char port_str[64]; -            const ssize_t port_str_len = ::snprintf (port_str, sizeof(port_str), "%u", port); -            // Write the port number as a C string with the NULL terminator -            ::write (fd, port_str, port_str_len + 1); -            close (fd); -        } +static void PortWasBoundCallbackNamedPipe(const void *baton, uint16_t port) { +  const char *named_pipe = (const char *)baton; +  if (named_pipe && named_pipe[0]) { +    int fd = ::open(named_pipe, O_WRONLY); +    if (fd > -1) { +      char port_str[64]; +      const ssize_t port_str_len = +          ::snprintf(port_str, sizeof(port_str), "%u", port); +      // Write the port number as a C string with the NULL terminator +      ::write(fd, port_str, port_str_len + 1); +      close(fd);      } +  }  } -static int -ConnectRemote (RNBRemote *remote, -               const char *host, -               int port, -               bool reverse_connect, -               const char *named_pipe_path, -               const char *unix_socket_name) -{ -    if (!remote->Comm().IsConnected()) -    { -        if (reverse_connect) -        { -            if (port == 0) -            { -                DNBLogThreaded("error: invalid port supplied for reverse connection: %i.\n", port); -                return 0; -            } -            if (remote->Comm().Connect(host, port) != rnb_success) -            { -                DNBLogThreaded("Failed to reverse connect to %s:%i.\n", host, port); -                return 0; -            } +static int ConnectRemote(RNBRemote *remote, const char *host, int port, +                         bool reverse_connect, const char *named_pipe_path, +                         const char *unix_socket_name) { +  if (!remote->Comm().IsConnected()) { +    if (reverse_connect) { +      if (port == 0) { +        DNBLogThreaded( +            "error: invalid port supplied for reverse connection: %i.\n", port); +        return 0; +      } +      if (remote->Comm().Connect(host, port) != rnb_success) { +        DNBLogThreaded("Failed to reverse connect to %s:%i.\n", host, port); +        return 0; +      } +    } else { +      if (port != 0) +        RNBLogSTDOUT("Listening to port %i for a connection from %s...\n", port, +                     host ? host : "127.0.0.1"); +      if (unix_socket_name && unix_socket_name[0]) { +        if (remote->Comm().Listen(host, port, PortWasBoundCallbackUnixSocket, +                                  unix_socket_name) != rnb_success) { +          RNBLogSTDERR("Failed to get connection from a remote gdb process.\n"); +          return 0;          } -        else -        { -            if (port != 0) -                RNBLogSTDOUT ("Listening to port %i for a connection from %s...\n", port, host ? host : "127.0.0.1"); -            if (unix_socket_name && unix_socket_name[0]) -            { -                if (remote->Comm().Listen(host, port, PortWasBoundCallbackUnixSocket, unix_socket_name) != rnb_success) -                { -                    RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n"); -                    return 0; -                } -            } -            else -            { -                if (remote->Comm().Listen(host, port, PortWasBoundCallbackNamedPipe, named_pipe_path) != rnb_success) -                { -                    RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n"); -                    return 0; -                } -            } +      } else { +        if (remote->Comm().Listen(host, port, PortWasBoundCallbackNamedPipe, +                                  named_pipe_path) != rnb_success) { +          RNBLogSTDERR("Failed to get connection from a remote gdb process.\n"); +          return 0;          } -        remote->StartReadRemoteDataThread(); +      }      } -    return 1; +    remote->StartReadRemoteDataThread(); +  } +  return 1;  }  //----------------------------------------------------------------------  // ASL Logging callback that can be registered with DNBLogSetLogCallback  //---------------------------------------------------------------------- -void -ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args) -{ -    if (format == NULL) -        return; -    static aslmsg g_aslmsg = NULL; -    if (g_aslmsg == NULL) -    { -        g_aslmsg = ::asl_new (ASL_TYPE_MSG); -        char asl_key_sender[PATH_MAX]; -        snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.%s-%s", DEBUGSERVER_PROGRAM_NAME, DEBUGSERVER_VERSION_STR); -        ::asl_set (g_aslmsg, ASL_KEY_SENDER, asl_key_sender); -    } - -    int asl_level; -    if (flags & DNBLOG_FLAG_FATAL)        asl_level = ASL_LEVEL_CRIT; -    else if (flags & DNBLOG_FLAG_ERROR)   asl_level = ASL_LEVEL_ERR; -    else if (flags & DNBLOG_FLAG_WARNING) asl_level = ASL_LEVEL_WARNING; -    else if (flags & DNBLOG_FLAG_VERBOSE) asl_level = ASL_LEVEL_WARNING; //ASL_LEVEL_INFO; -    else                                  asl_level = ASL_LEVEL_WARNING; //ASL_LEVEL_DEBUG; - -    ::asl_vlog (NULL, g_aslmsg, asl_level, format, args); +void ASLLogCallback(void *baton, uint32_t flags, const char *format, +                    va_list args) { +  if (format == NULL) +    return; +  static aslmsg g_aslmsg = NULL; +  if (g_aslmsg == NULL) { +    g_aslmsg = ::asl_new(ASL_TYPE_MSG); +    char asl_key_sender[PATH_MAX]; +    snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.%s-%s", +             DEBUGSERVER_PROGRAM_NAME, DEBUGSERVER_VERSION_STR); +    ::asl_set(g_aslmsg, ASL_KEY_SENDER, asl_key_sender); +  } + +  int asl_level; +  if (flags & DNBLOG_FLAG_FATAL) +    asl_level = ASL_LEVEL_CRIT; +  else if (flags & DNBLOG_FLAG_ERROR) +    asl_level = ASL_LEVEL_ERR; +  else if (flags & DNBLOG_FLAG_WARNING) +    asl_level = ASL_LEVEL_WARNING; +  else if (flags & DNBLOG_FLAG_VERBOSE) +    asl_level = ASL_LEVEL_WARNING; // ASL_LEVEL_INFO; +  else +    asl_level = ASL_LEVEL_WARNING; // ASL_LEVEL_DEBUG; + +  ::asl_vlog(NULL, g_aslmsg, asl_level, format, args);  }  //----------------------------------------------------------------------  // FILE based Logging callback that can be registered with  // DNBLogSetLogCallback  //---------------------------------------------------------------------- -void -FileLogCallback(void *baton, uint32_t flags, const char *format, va_list args) -{ -    if (baton == NULL || format == NULL) -        return; - -    ::vfprintf((FILE *)baton, format, args); -    ::fprintf((FILE *)baton, "\n"); -    ::fflush((FILE *)baton); +void FileLogCallback(void *baton, uint32_t flags, const char *format, +                     va_list args) { +  if (baton == NULL || format == NULL) +    return; + +  ::vfprintf((FILE *)baton, format, args); +  ::fprintf((FILE *)baton, "\n"); +  ::fflush((FILE *)baton);  } - -void -show_usage_and_exit (int exit_code) -{ -    RNBLogSTDERR ("Usage:\n  %s host:port [program-name program-arg1 program-arg2 ...]\n", DEBUGSERVER_PROGRAM_NAME); -    RNBLogSTDERR ("  %s /path/file [program-name program-arg1 program-arg2 ...]\n", DEBUGSERVER_PROGRAM_NAME); -    RNBLogSTDERR ("  %s host:port --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); -    RNBLogSTDERR ("  %s /path/file --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); -    RNBLogSTDERR ("  %s host:port --attach=<process_name>\n", DEBUGSERVER_PROGRAM_NAME); -    RNBLogSTDERR ("  %s /path/file --attach=<process_name>\n", DEBUGSERVER_PROGRAM_NAME); -    exit (exit_code); +void show_usage_and_exit(int exit_code) { +  RNBLogSTDERR( +      "Usage:\n  %s host:port [program-name program-arg1 program-arg2 ...]\n", +      DEBUGSERVER_PROGRAM_NAME); +  RNBLogSTDERR("  %s /path/file [program-name program-arg1 program-arg2 ...]\n", +               DEBUGSERVER_PROGRAM_NAME); +  RNBLogSTDERR("  %s host:port --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); +  RNBLogSTDERR("  %s /path/file --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); +  RNBLogSTDERR("  %s host:port --attach=<process_name>\n", +               DEBUGSERVER_PROGRAM_NAME); +  RNBLogSTDERR("  %s /path/file --attach=<process_name>\n", +               DEBUGSERVER_PROGRAM_NAME); +  exit(exit_code);  } -  //----------------------------------------------------------------------  // option descriptors for getopt_long_only()  //---------------------------------------------------------------------- -static struct option g_long_options[] = -{ -    { "attach",             required_argument,  NULL,               'a' }, -    { "arch",               required_argument,  NULL,               'A' }, -    { "debug",              no_argument,        NULL,               'g' }, -    { "kill-on-error",      no_argument,        NULL,               'K' }, -    { "verbose",            no_argument,        NULL,               'v' }, -    { "lockdown",           no_argument,        &g_lockdown_opt,    1   },  // short option "-k" -    { "applist",            no_argument,        &g_applist_opt,     1   },  // short option "-t" -    { "log-file",           required_argument,  NULL,               'l' }, -    { "log-flags",          required_argument,  NULL,               'f' }, -    { "launch",             required_argument,  NULL,               'x' },  // Valid values are "auto", "posix-spawn", "fork-exec", "springboard" (arm only) -    { "waitfor",            required_argument,  NULL,               'w' },  // Wait for a process whose name starts with ARG -    { "waitfor-interval",   required_argument,  NULL,               'i' },  // Time in usecs to wait between sampling the pid list when waiting for a process by name -    { "waitfor-duration",   required_argument,  NULL,               'd' },  // The time in seconds to wait for a process to show up by name -    { "native-regs",        no_argument,        NULL,               'r' },  // Specify to use the native registers instead of the gdb defaults for the architecture. -    { "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) -    { "stdin-path",         required_argument,  NULL,               'I' },  // Set the STDIN path to be used when launching applications (only if debugserver launches the process) -    { "stdout-path",        required_argument,  NULL,               'O' },  // Set the STDOUT path to be used when launching applications (only if debugserver launches the process) -    { "stderr-path",        required_argument,  NULL,               'E' },  // Set the STDERR path to be used when launching applications (only if debugserver launches the process) -    { "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) -    { "setsid",             no_argument,        NULL,               'S' },  // call setsid() to make debugserver run in its own session -    { "disable-aslr",       no_argument,        NULL,               'D' },  // Use _POSIX_SPAWN_DISABLE_ASLR to avoid shared library randomization -    { "working-dir",        required_argument,  NULL,               'W' },  // The working directory that the inferior process should have (only if debugserver launches the process) -    { "platform",           required_argument,  NULL,               'p' },  // Put this executable into a remote platform mode -    { "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 -    { "named-pipe",         required_argument,  NULL,               'P' }, -    { "reverse-connect",    no_argument,        NULL,               'R' }, -    { "env",                required_argument,  NULL,               'e' },  // When debugserver launches the process, set a single environment entry as specified by the option value ("./debugserver -e FOO=1 -e BAR=2 localhost:1234 -- /bin/ls") -    { "forward-env",        no_argument,        NULL,               'F' },  // When debugserver launches the process, forward debugserver's current environment variables to the child process ("./debugserver -F localhost:1234 -- /bin/ls" -    { NULL,                 0,                  NULL,               0   } -}; - +static struct option g_long_options[] = { +    {"attach", required_argument, NULL, 'a'}, +    {"arch", required_argument, NULL, 'A'}, +    {"debug", no_argument, NULL, 'g'}, +    {"kill-on-error", no_argument, NULL, 'K'}, +    {"verbose", no_argument, NULL, 'v'}, +    {"lockdown", no_argument, &g_lockdown_opt, 1}, // short option "-k" +    {"applist", no_argument, &g_applist_opt, 1},   // short option "-t" +    {"log-file", required_argument, NULL, 'l'}, +    {"log-flags", required_argument, NULL, 'f'}, +    {"launch", required_argument, NULL, 'x'}, // Valid values are "auto", +                                              // "posix-spawn", "fork-exec", +                                              // "springboard" (arm only) +    {"waitfor", required_argument, NULL, +     'w'}, // Wait for a process whose name starts with ARG +    {"waitfor-interval", required_argument, NULL, +     'i'}, // Time in usecs to wait between sampling the pid list when waiting +           // for a process by name +    {"waitfor-duration", required_argument, NULL, +     'd'}, // The time in seconds to wait for a process to show up by name +    {"native-regs", no_argument, NULL, 'r'}, // Specify to use the native +                                             // registers instead of the gdb +                                             // defaults for the architecture. +    {"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) +    {"stdin-path", required_argument, NULL, +     'I'}, // Set the STDIN path to be used when launching applications (only if +           // debugserver launches the process) +    {"stdout-path", required_argument, NULL, +     'O'}, // Set the STDOUT path to be used when launching applications (only +           // if debugserver launches the process) +    {"stderr-path", required_argument, NULL, +     'E'}, // Set the STDERR path to be used when launching applications (only +           // if debugserver launches the process) +    {"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) +    {"setsid", no_argument, NULL, +     'S'}, // call setsid() to make debugserver run in its own session +    {"disable-aslr", no_argument, NULL, 'D'}, // Use _POSIX_SPAWN_DISABLE_ASLR +                                              // to avoid shared library +                                              // randomization +    {"working-dir", required_argument, NULL, +     'W'}, // The working directory that the inferior process should have (only +           // if debugserver launches the process) +    {"platform", required_argument, NULL, +     'p'}, // Put this executable into a remote platform mode +    {"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 +    {"fd", required_argument, NULL, +     'FDSC'}, // A file descriptor was passed to this process when spawned that +              // is already open and ready for communication +    {"named-pipe", required_argument, NULL, 'P'}, +    {"reverse-connect", no_argument, NULL, 'R'}, +    {"env", required_argument, NULL, +     'e'}, // When debugserver launches the process, set a single environment +           // entry as specified by the option value ("./debugserver -e FOO=1 -e +           // BAR=2 localhost:1234 -- /bin/ls") +    {"forward-env", no_argument, NULL, +     'F'}, // When debugserver launches the process, forward debugserver's +           // current environment variables to the child process ("./debugserver +           // -F localhost:1234 -- /bin/ls" +    {NULL, 0, NULL, 0}};  //----------------------------------------------------------------------  // main  //---------------------------------------------------------------------- -int -main (int argc, char *argv[]) -{ -    // If debugserver is launched with DYLD_INSERT_LIBRARIES, unset it so we -    // don't spawn child processes with this enabled. -    unsetenv("DYLD_INSERT_LIBRARIES"); - -    const char *argv_sub_zero = argv[0]; // save a copy of argv[0] for error reporting post-launch - -#if defined (__APPLE__) -    pthread_setname_np ("main thread"); -#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) -    struct sched_param thread_param; -    int thread_sched_policy; -    if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0) -    { -        thread_param.sched_priority = 47; -        pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); -    } - -    ::proc_set_wakemon_params (getpid(), 500, 0); // Allow up to 500 wakeups/sec to avoid EXC_RESOURCE for normal use. +int main(int argc, char *argv[]) { +  // If debugserver is launched with DYLD_INSERT_LIBRARIES, unset it so we +  // don't spawn child processes with this enabled. +  unsetenv("DYLD_INSERT_LIBRARIES"); + +  const char *argv_sub_zero = +      argv[0]; // save a copy of argv[0] for error reporting post-launch + +#if defined(__APPLE__) +  pthread_setname_np("main thread"); +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) +  struct sched_param thread_param; +  int thread_sched_policy; +  if (pthread_getschedparam(pthread_self(), &thread_sched_policy, +                            &thread_param) == 0) { +    thread_param.sched_priority = 47; +    pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); +  } + +  ::proc_set_wakemon_params( +      getpid(), 500, +      0); // Allow up to 500 wakeups/sec to avoid EXC_RESOURCE for normal use.  #endif  #endif -    g_isatty = ::isatty (STDIN_FILENO); - -    //  ::printf ("uid=%u euid=%u gid=%u egid=%u\n", -    //            getuid(), -    //            geteuid(), -    //            getgid(), -    //            getegid()); - - -    //    signal (SIGINT, signal_handler); -    signal (SIGPIPE, signal_handler); -    signal (SIGHUP, signal_handler); - -    // We're always sitting in waitpid or kevent waiting on our target process' death, -    // we don't need no stinking SIGCHLD's... - -    sigset_t sigset; -    sigemptyset(&sigset); -    sigaddset(&sigset, SIGCHLD); -    sigprocmask(SIG_BLOCK, &sigset, NULL); - -    g_remoteSP.reset (new RNBRemote ()); - - -    RNBRemote *remote = g_remoteSP.get(); -    if (remote == NULL) -    { -        RNBLogSTDERR ("error: failed to create a remote connection class\n"); -        return -1; -    } - -    RNBContext& ctx = remote->Context(); - -    int i; -    int attach_pid = INVALID_NUB_PROCESS; - -    FILE* log_file = NULL; -    uint32_t log_flags = 0; -    // Parse our options -    int ch; -    int long_option_index = 0; -    int debug = 0; -    std::string compile_options; -    std::string waitfor_pid_name;           // Wait for a process that starts with this name -    std::string attach_pid_name; -    std::string arch_name; -    std::string working_dir;                // The new working directory to use for the inferior -    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 -    std::string named_pipe_path;            // If we need to handshake with our parent process, an option will be passed down that specifies a named pipe to use -    useconds_t waitfor_interval = 1000;     // Time in usecs between process lists polls when waiting for a process by name, default 1 msec. -    useconds_t waitfor_duration = 0;        // Time in seconds to wait for a process by name, 0 means wait forever. -    bool no_stdio = false; -    bool reverse_connect = false;           // Set to true by an option to indicate we should reverse connect to the host:port supplied as the first debugserver argument - -#if !defined (DNBLOG_ENABLED) -    compile_options += "(no-logging) "; +  g_isatty = ::isatty(STDIN_FILENO); + +  //  ::printf ("uid=%u euid=%u gid=%u egid=%u\n", +  //            getuid(), +  //            geteuid(), +  //            getgid(), +  //            getegid()); + +  //    signal (SIGINT, signal_handler); +  signal(SIGPIPE, signal_handler); +  signal(SIGHUP, signal_handler); + +  // We're always sitting in waitpid or kevent waiting on our target process' +  // death, +  // we don't need no stinking SIGCHLD's... + +  sigset_t sigset; +  sigemptyset(&sigset); +  sigaddset(&sigset, SIGCHLD); +  sigprocmask(SIG_BLOCK, &sigset, NULL); + +  g_remoteSP.reset(new RNBRemote()); + +  RNBRemote *remote = g_remoteSP.get(); +  if (remote == NULL) { +    RNBLogSTDERR("error: failed to create a remote connection class\n"); +    return -1; +  } + +  RNBContext &ctx = remote->Context(); + +  int i; +  int attach_pid = INVALID_NUB_PROCESS; + +  FILE *log_file = NULL; +  uint32_t log_flags = 0; +  // Parse our options +  int ch; +  int long_option_index = 0; +  int debug = 0; +  int communication_fd = -1; +  std::string compile_options; +  std::string waitfor_pid_name; // Wait for a process that starts with this name +  std::string attach_pid_name; +  std::string arch_name; +  std::string working_dir; // The new working directory to use for the inferior +  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 +  std::string named_pipe_path;  // If we need to handshake with our parent +                                // process, an option will be passed down that +                                // specifies a named pipe to use +  useconds_t waitfor_interval = 1000; // Time in usecs between process lists +                                      // polls when waiting for a process by +                                      // name, default 1 msec. +  useconds_t waitfor_duration = +      0; // Time in seconds to wait for a process by name, 0 means wait forever. +  bool no_stdio = false; +  bool reverse_connect = false; // Set to true by an option to indicate we +                                // should reverse connect to the host:port +                                // supplied as the first debugserver argument + +#if !defined(DNBLOG_ENABLED) +  compile_options += "(no-logging) ";  #endif -    RNBRunLoopMode start_mode = eRNBRunLoopModeExit; - -    char short_options[512]; -    uint32_t short_options_idx = 0; - -     // Handle the two case that don't have short options in g_long_options -    short_options[short_options_idx++] = 'k'; -    short_options[short_options_idx++] = 't'; - -    for (i=0; g_long_options[i].name != NULL; ++i) -    { -        if (isalpha(g_long_options[i].val)) -        { -            short_options[short_options_idx++] = g_long_options[i].val; -            switch (g_long_options[i].has_arg) -            { -                default: -                case no_argument: -                    break; - -                case optional_argument: -                    short_options[short_options_idx++] = ':'; -                    // Fall through to required_argument case below... -                case required_argument: -                    short_options[short_options_idx++] = ':'; -                    break; -            } -        } +  RNBRunLoopMode start_mode = eRNBRunLoopModeExit; + +  char short_options[512]; +  uint32_t short_options_idx = 0; + +  // Handle the two case that don't have short options in g_long_options +  short_options[short_options_idx++] = 'k'; +  short_options[short_options_idx++] = 't'; + +  for (i = 0; g_long_options[i].name != NULL; ++i) { +    if (isalpha(g_long_options[i].val)) { +      short_options[short_options_idx++] = g_long_options[i].val; +      switch (g_long_options[i].has_arg) { +      default: +      case no_argument: +        break; + +      case optional_argument: +        short_options[short_options_idx++] = ':'; +      // Fall through to required_argument case below... +      case required_argument: +        short_options[short_options_idx++] = ':'; +        break; +      }      } -    // NULL terminate the short option string. -    short_options[short_options_idx++] = '\0'; +  } +  // NULL terminate the short option string. +  short_options[short_options_idx++] = '\0';  #if __GLIBC__ -    optind = 0; +  optind = 0;  #else -    optreset = 1; -    optind = 1; +  optreset = 1; +  optind = 1;  #endif -    while ((ch = getopt_long_only(argc, argv, short_options, g_long_options, &long_option_index)) != -1) -    { -        DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", -                    ch, (uint8_t)ch, -                    g_long_options[long_option_index].name, -                    g_long_options[long_option_index].has_arg ? '=' : ' ', -                    optarg ? optarg : ""); -        switch (ch) -        { -            case 0:   // Any optional that auto set themselves will return 0 -                break; - -            case 'A': -                if (optarg && optarg[0]) -                    arch_name.assign(optarg); -                break; - -            case 'a': -                if (optarg && optarg[0]) -                { -                    if (isdigit(optarg[0])) -                    { -                        char *end = NULL; -                        attach_pid = static_cast<int>(strtoul(optarg, &end, 0)); -                        if (end == NULL || *end != '\0') -                        { -                            RNBLogSTDERR ("error: invalid pid option '%s'\n", optarg); -                            exit (4); -                        } -                    } -                    else -                    { -                        attach_pid_name = optarg; -                    } -                    start_mode = eRNBRunLoopModeInferiorAttaching; -                } -                break; - -                // --waitfor=NAME -            case 'w': -                if (optarg && optarg[0]) -                { -                    waitfor_pid_name = optarg; -                    start_mode = eRNBRunLoopModeInferiorAttaching; -                } -                break; - -                // --waitfor-interval=USEC -            case 'i': -                if (optarg && optarg[0]) -                { -                    char *end = NULL; -                    waitfor_interval = static_cast<useconds_t>(strtoul(optarg, &end, 0)); -                    if (end == NULL || *end != '\0') -                    { -                        RNBLogSTDERR ("error: invalid waitfor-interval option value '%s'.\n", optarg); -                        exit (6); -                    } -                } -                break; - -                // --waitfor-duration=SEC -            case 'd': -                if (optarg && optarg[0]) -                { -                    char *end = NULL; -                    waitfor_duration = static_cast<useconds_t>(strtoul(optarg, &end, 0)); -                    if (end == NULL || *end != '\0') -                    { -                        RNBLogSTDERR ("error: invalid waitfor-duration option value '%s'.\n", optarg); -                        exit (7); -                    } -                } -                break; - -            case 'K': -                g_detach_on_error = false; -                break; -            case 'W': -                if (optarg && optarg[0]) -                    working_dir.assign(optarg); -                break; - -            case 'x': -                if (optarg && optarg[0]) -                { -                    if (strcasecmp(optarg, "auto") == 0) -                        g_launch_flavor = eLaunchFlavorDefault; -                    else if (strcasestr(optarg, "posix") == optarg) -                        g_launch_flavor = eLaunchFlavorPosixSpawn; -                    else if (strcasestr(optarg, "fork") == optarg) -                        g_launch_flavor = eLaunchFlavorForkExec; +  while ((ch = getopt_long_only(argc, argv, short_options, g_long_options, +                                &long_option_index)) != -1) { +    DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", ch, (uint8_t)ch, +                g_long_options[long_option_index].name, +                g_long_options[long_option_index].has_arg ? '=' : ' ', +                optarg ? optarg : ""); +    switch (ch) { +    case 0: // Any optional that auto set themselves will return 0 +      break; + +    case 'A': +      if (optarg && optarg[0]) +        arch_name.assign(optarg); +      break; + +    case 'a': +      if (optarg && optarg[0]) { +        if (isdigit(optarg[0])) { +          char *end = NULL; +          attach_pid = static_cast<int>(strtoul(optarg, &end, 0)); +          if (end == NULL || *end != '\0') { +            RNBLogSTDERR("error: invalid pid option '%s'\n", optarg); +            exit(4); +          } +        } else { +          attach_pid_name = optarg; +        } +        start_mode = eRNBRunLoopModeInferiorAttaching; +      } +      break; + +    // --waitfor=NAME +    case 'w': +      if (optarg && optarg[0]) { +        waitfor_pid_name = optarg; +        start_mode = eRNBRunLoopModeInferiorAttaching; +      } +      break; + +    // --waitfor-interval=USEC +    case 'i': +      if (optarg && optarg[0]) { +        char *end = NULL; +        waitfor_interval = static_cast<useconds_t>(strtoul(optarg, &end, 0)); +        if (end == NULL || *end != '\0') { +          RNBLogSTDERR("error: invalid waitfor-interval option value '%s'.\n", +                       optarg); +          exit(6); +        } +      } +      break; + +    // --waitfor-duration=SEC +    case 'd': +      if (optarg && optarg[0]) { +        char *end = NULL; +        waitfor_duration = static_cast<useconds_t>(strtoul(optarg, &end, 0)); +        if (end == NULL || *end != '\0') { +          RNBLogSTDERR("error: invalid waitfor-duration option value '%s'.\n", +                       optarg); +          exit(7); +        } +      } +      break; + +    case 'K': +      g_detach_on_error = false; +      break; +    case 'W': +      if (optarg && optarg[0]) +        working_dir.assign(optarg); +      break; + +    case 'x': +      if (optarg && optarg[0]) { +        if (strcasecmp(optarg, "auto") == 0) +          g_launch_flavor = eLaunchFlavorDefault; +        else if (strcasestr(optarg, "posix") == optarg) +          g_launch_flavor = eLaunchFlavorPosixSpawn; +        else if (strcasestr(optarg, "fork") == optarg) +          g_launch_flavor = eLaunchFlavorForkExec;  #ifdef WITH_SPRINGBOARD -                    else if (strcasestr(optarg, "spring") == optarg) -                        g_launch_flavor = eLaunchFlavorSpringBoard; +        else if (strcasestr(optarg, "spring") == optarg) +          g_launch_flavor = eLaunchFlavorSpringBoard;  #endif  #ifdef WITH_BKS -                    else if (strcasestr(optarg, "backboard") == optarg) -                        g_launch_flavor = eLaunchFlavorBKS; +        else if (strcasestr(optarg, "backboard") == optarg) +          g_launch_flavor = eLaunchFlavorBKS;  #endif  #ifdef WITH_FBS -                    else if (strcasestr(optarg, "frontboard") == optarg) -                        g_launch_flavor = eLaunchFlavorFBS; +        else if (strcasestr(optarg, "frontboard") == optarg) +          g_launch_flavor = eLaunchFlavorFBS;  #endif -                    else -                    { -                        RNBLogSTDERR ("error: invalid TYPE for the --launch=TYPE (-x TYPE) option: '%s'\n", optarg); -                        RNBLogSTDERR ("Valid values TYPE are:\n"); -                        RNBLogSTDERR ("  auto       Auto-detect the best launch method to use.\n"); -                        RNBLogSTDERR ("  posix      Launch the executable using posix_spawn.\n"); -                        RNBLogSTDERR ("  fork       Launch the executable using fork and exec.\n"); +        else { +          RNBLogSTDERR("error: invalid TYPE for the --launch=TYPE (-x TYPE) " +                       "option: '%s'\n", +                       optarg); +          RNBLogSTDERR("Valid values TYPE are:\n"); +          RNBLogSTDERR( +              "  auto       Auto-detect the best launch method to use.\n"); +          RNBLogSTDERR( +              "  posix      Launch the executable using posix_spawn.\n"); +          RNBLogSTDERR( +              "  fork       Launch the executable using fork and exec.\n");  #ifdef WITH_SPRINGBOARD -                        RNBLogSTDERR ("  spring     Launch the executable through Springboard.\n"); +          RNBLogSTDERR( +              "  spring     Launch the executable through Springboard.\n");  #endif  #ifdef WITH_BKS -                        RNBLogSTDERR ("  backboard  Launch the executable through BackBoard Services.\n"); +          RNBLogSTDERR("  backboard  Launch the executable through BackBoard " +                       "Services.\n");  #endif  #ifdef WITH_FBS -                        RNBLogSTDERR ("  frontboard  Launch the executable through FrontBoard Services.\n"); +          RNBLogSTDERR("  frontboard  Launch the executable through FrontBoard " +                       "Services.\n");  #endif -                        exit (5); -                    } -                } -                break; - -            case 'l': // Set Log File -                if (optarg && optarg[0]) -                { -                    if (strcasecmp(optarg, "stdout") == 0) -                        log_file = stdout; -                    else if (strcasecmp(optarg, "stderr") == 0) -                        log_file = stderr; -                    else -                    { -                        log_file = fopen(optarg, "w"); -                        if (log_file != NULL) -                            setlinebuf(log_file); -                    } - -                    if (log_file == NULL) -                    { -                        const char *errno_str = strerror(errno); -                        RNBLogSTDERR ("Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error"); -                    } -                } -                break; - -            case 'f': // Log Flags -                if (optarg && optarg[0]) -                    log_flags = static_cast<uint32_t>(strtoul(optarg, NULL, 0)); -                break; - -            case 'g': -                debug = 1; -                DNBLogSetDebug(debug); -                break; - -            case 't': -                g_applist_opt = 1; -                break; - -            case 'k': -                g_lockdown_opt = 1; -                break; - -            case 'r': -                // Do nothing, native regs is the default these days -                break; - -            case 'R': -                reverse_connect = true; -                break; -            case 'v': -                DNBLogSetVerbose(1); -                break; - -            case 's': -                ctx.GetSTDIN().assign(optarg); -                ctx.GetSTDOUT().assign(optarg); -                ctx.GetSTDERR().assign(optarg); -                break; - -            case 'I': -                ctx.GetSTDIN().assign(optarg); -                break; - -            case 'O': -                ctx.GetSTDOUT().assign(optarg); -                break; - -            case 'E': -                ctx.GetSTDERR().assign(optarg); -                break; - -            case 'n': -                no_stdio = true; -                break; - -            case 'S': -                // Put debugserver into a new session. Terminals group processes -                // into sessions and when a special terminal key sequences -                // (like control+c) are typed they can cause signals to go out to -                // all processes in a session. Using this --setsid (-S) option -                // will cause debugserver to run in its own sessions and be free -                // from such issues. -                // -                // This is useful when debugserver is spawned from a command -                // line application that uses debugserver to do the debugging, -                // yet that application doesn't want debugserver receiving the -                // signals sent to the session (i.e. dying when anyone hits ^C). -                setsid(); -                break; -            case 'D': -                g_disable_aslr = 1; -                break; - -            case 'p': -                start_mode = eRNBRunLoopModePlatformMode; -                break; - -            case 'u': -                unix_socket_name.assign (optarg); -                break; - -            case 'P': -                named_pipe_path.assign (optarg); -                break; - -            case 'e': -                // Pass a single specified environment variable down to the process that gets launched -                remote->Context().PushEnvironment(optarg); -                break; - -            case 'F': -                // Pass the current environment down to the process that gets launched -                { -                    char **host_env = *_NSGetEnviron(); -                    char *env_entry; -                    size_t i; -                    for (i=0; (env_entry = host_env[i]) != NULL; ++i) -                        remote->Context().PushEnvironment(env_entry); -                } -                break; +          exit(5); +        } +      } +      break; + +    case 'l': // Set Log File +      if (optarg && optarg[0]) { +        if (strcasecmp(optarg, "stdout") == 0) +          log_file = stdout; +        else if (strcasecmp(optarg, "stderr") == 0) +          log_file = stderr; +        else { +          log_file = fopen(optarg, "w"); +          if (log_file != NULL) +            setlinebuf(log_file);          } -    } -    if (arch_name.empty()) -    { -#if defined (__arm__) -        arch_name.assign ("arm"); -#endif -    } -    else -    { -        DNBSetArchitecture (arch_name.c_str()); +        if (log_file == NULL) { +          const char *errno_str = strerror(errno); +          RNBLogSTDERR( +              "Failed to open log file '%s' for writing: errno = %i (%s)", +              optarg, errno, errno_str ? errno_str : "unknown error"); +        } +      } +      break; + +    case 'f': // Log Flags +      if (optarg && optarg[0]) +        log_flags = static_cast<uint32_t>(strtoul(optarg, NULL, 0)); +      break; + +    case 'g': +      debug = 1; +      DNBLogSetDebug(debug); +      break; + +    case 't': +      g_applist_opt = 1; +      break; + +    case 'k': +      g_lockdown_opt = 1; +      break; + +    case 'r': +      // Do nothing, native regs is the default these days +      break; + +    case 'R': +      reverse_connect = true; +      break; +    case 'v': +      DNBLogSetVerbose(1); +      break; + +    case 's': +      ctx.GetSTDIN().assign(optarg); +      ctx.GetSTDOUT().assign(optarg); +      ctx.GetSTDERR().assign(optarg); +      break; + +    case 'I': +      ctx.GetSTDIN().assign(optarg); +      break; + +    case 'O': +      ctx.GetSTDOUT().assign(optarg); +      break; + +    case 'E': +      ctx.GetSTDERR().assign(optarg); +      break; + +    case 'n': +      no_stdio = true; +      break; + +    case 'S': +      // Put debugserver into a new session. Terminals group processes +      // into sessions and when a special terminal key sequences +      // (like control+c) are typed they can cause signals to go out to +      // all processes in a session. Using this --setsid (-S) option +      // will cause debugserver to run in its own sessions and be free +      // from such issues. +      // +      // This is useful when debugserver is spawned from a command +      // line application that uses debugserver to do the debugging, +      // yet that application doesn't want debugserver receiving the +      // signals sent to the session (i.e. dying when anyone hits ^C). +      setsid(); +      break; +    case 'D': +      g_disable_aslr = 1; +      break; + +    case 'p': +      start_mode = eRNBRunLoopModePlatformMode; +      break; + +    case 'u': +      unix_socket_name.assign(optarg); +      break; + +    case 'P': +      named_pipe_path.assign(optarg); +      break; + +    case 'e': +      // Pass a single specified environment variable down to the process that +      // gets launched +      remote->Context().PushEnvironment(optarg); +      break; + +    case 'F': +      // Pass the current environment down to the process that gets launched +      { +        char **host_env = *_NSGetEnviron(); +        char *env_entry; +        size_t i; +        for (i = 0; (env_entry = host_env[i]) != NULL; ++i) +          remote->Context().PushEnvironment(env_entry); +      } +      break; + +    case 'FDSC': +      // File descriptor passed to this process during fork/exec and is already +      // open and ready for communication. +      communication_fd = atoi(optarg); +      break;      } +  } -//    if (arch_name.empty()) -//    { -//        fprintf(stderr, "error: no architecture was specified\n"); -//        exit (8); -//    } -    // Skip any options we consumed with getopt_long_only -    argc -= optind; -    argv += optind; - - -    if (!working_dir.empty()) -    { -        if (remote->Context().SetWorkingDirectory (working_dir.c_str()) == false) -        { -            RNBLogSTDERR ("error: working directory doesn't exist '%s'.\n", working_dir.c_str()); -            exit (8); -        } +  if (arch_name.empty()) { +#if defined(__arm__) +    arch_name.assign("arm"); +#endif +  } else { +    DNBSetArchitecture(arch_name.c_str()); +  } + +  //    if (arch_name.empty()) +  //    { +  //        fprintf(stderr, "error: no architecture was specified\n"); +  //        exit (8); +  //    } +  // Skip any options we consumed with getopt_long_only +  argc -= optind; +  argv += optind; + +  if (!working_dir.empty()) { +    if (remote->Context().SetWorkingDirectory(working_dir.c_str()) == false) { +      RNBLogSTDERR("error: working directory doesn't exist '%s'.\n", +                   working_dir.c_str()); +      exit(8);      } +  } -    remote->Context().SetDetachOnError(g_detach_on_error); +  remote->Context().SetDetachOnError(g_detach_on_error); -    remote->Initialize(); +  remote->Initialize(); -    // It is ok for us to set NULL as the logfile (this will disable any logging) +  // It is ok for us to set NULL as the logfile (this will disable any logging) -    if (log_file != NULL) -    { -        DNBLogSetLogCallback(FileLogCallback, log_file); -        // If our log file was set, yet we have no log flags, log everything! -        if (log_flags == 0) -            log_flags = LOG_ALL | LOG_RNB_ALL; +  if (log_file != NULL) { +    DNBLogSetLogCallback(FileLogCallback, log_file); +    // If our log file was set, yet we have no log flags, log everything! +    if (log_flags == 0) +      log_flags = LOG_ALL | LOG_RNB_ALL; -        DNBLogSetLogMask (log_flags); -    } -    else -    { -        // Enable DNB logging -        DNBLogSetLogCallback(ASLLogCallback, NULL); -        DNBLogSetLogMask (log_flags); +    DNBLogSetLogMask(log_flags); +  } else { +    // Enable DNB logging +    // if os_log() support is available, log through that. +    auto log_callback = OsLogger::GetLogFunction(); +    if (log_callback) { +      DNBLogSetLogCallback(log_callback, nullptr); +      DNBLog("debugserver will use os_log for internal logging."); +    } else { +      // Fall back to ASL support. +      DNBLogSetLogCallback(ASLLogCallback, NULL); +      DNBLog("debugserver will use ASL for internal logging.");      } +    DNBLogSetLogMask(log_flags); +  } -    if (DNBLogEnabled()) -    { -        for (i=0; i<argc; i++) -            DNBLogDebug("argv[%i] = %s", i, argv[i]); -    } +  if (DNBLogEnabled()) { +    for (i = 0; i < argc; i++) +      DNBLogDebug("argv[%i] = %s", i, argv[i]); +  } -    // as long as we're dropping remotenub in as a replacement for gdbserver, -    // explicitly note that this is not gdbserver. - -    RNBLogSTDOUT ("%s-%s %sfor %s.\n", -                  DEBUGSERVER_PROGRAM_NAME, -                  DEBUGSERVER_VERSION_STR, -                  compile_options.c_str(), -                  RNB_ARCH); - -    std::string host; -    int port = INT32_MAX; -    char str[PATH_MAX]; -    str[0] = '\0'; - -    if (g_lockdown_opt == 0 && g_applist_opt == 0) -    { -        // Make sure we at least have port -        if (argc < 1) -        { -            show_usage_and_exit (1); -        } -        // accept 'localhost:' prefix on port number +  // as long as we're dropping remotenub in as a replacement for gdbserver, +  // explicitly note that this is not gdbserver. -        int items_scanned = ::sscanf (argv[0], "%[^:]:%i", str, &port); -        if (items_scanned == 2) -        { -            host = str; -            DNBLogDebug("host = '%s'  port = %i", host.c_str(), port); -        } -        else -        { -            // No hostname means "localhost" -            int items_scanned = ::sscanf (argv[0], "%i", &port); -            if (items_scanned == 1) -            { -                host = "127.0.0.1"; -                DNBLogDebug("host = '%s'  port = %i", host.c_str(), port); -            } -            else if (argv[0][0] == '/') -            { -                port = INT32_MAX; -                strncpy(str, argv[0], sizeof(str)); -            } -            else -            { -                show_usage_and_exit (2); -            } -        } +  RNBLogSTDOUT("%s-%s %sfor %s.\n", DEBUGSERVER_PROGRAM_NAME, +               DEBUGSERVER_VERSION_STR, compile_options.c_str(), RNB_ARCH); -        // We just used the 'host:port' or the '/path/file' arg... -        argc--; -        argv++; +  std::string host; +  int port = INT32_MAX; +  char str[PATH_MAX]; +  str[0] = '\0'; +  if (g_lockdown_opt == 0 && g_applist_opt == 0 && communication_fd == -1) { +    // Make sure we at least have port +    if (argc < 1) { +      show_usage_and_exit(1); +    } +    // accept 'localhost:' prefix on port number + +    int items_scanned = ::sscanf(argv[0], "%[^:]:%i", str, &port); +    if (items_scanned == 2) { +      host = str; +      DNBLogDebug("host = '%s'  port = %i", host.c_str(), port); +    } else { +      // No hostname means "localhost" +      int items_scanned = ::sscanf(argv[0], "%i", &port); +      if (items_scanned == 1) { +        host = "127.0.0.1"; +        DNBLogDebug("host = '%s'  port = %i", host.c_str(), port); +      } else if (argv[0][0] == '/') { +        port = INT32_MAX; +        strncpy(str, argv[0], sizeof(str)); +      } else { +        show_usage_and_exit(2); +      }      } -    //  If we know we're waiting to attach, we don't need any of this other info. -    if (start_mode != eRNBRunLoopModeInferiorAttaching && -        start_mode != eRNBRunLoopModePlatformMode) -    { -        if (argc == 0 || g_lockdown_opt) -        { -            if (g_lockdown_opt != 0) -            { -                // Work around for SIGPIPE crashes due to posix_spawn issue. -                // We have to close STDOUT and STDERR, else the first time we -                // try and do any, we get SIGPIPE and die as posix_spawn is -                // doing bad things with our file descriptors at the moment. -                int null = open("/dev/null", O_RDWR); -                dup2(null, STDOUT_FILENO); -                dup2(null, STDERR_FILENO); -            } -            else if (g_applist_opt != 0) -            { -                // List all applications we are able to see -                std::string applist_plist; -                int err = ListApplications(applist_plist, false, false); -                if (err == 0) -                { -                    fputs (applist_plist.c_str(), stdout); -                } -                else -                { -                    RNBLogSTDERR ("error: ListApplications returned error %i\n", err); -                } -                // Exit with appropriate error if we were asked to list the applications -                // with no other args were given (and we weren't trying to do this over -                // lockdown) -                return err; -            } - -            DNBLogDebug("Get args from remote protocol..."); -            start_mode = eRNBRunLoopModeGetStartModeFromRemoteProtocol; -        } -        else -        { -            start_mode = eRNBRunLoopModeInferiorLaunching; -            // Fill in the argv array in the context from the rest of our args. -            // Skip the name of this executable and the port number -            for (int i = 0; i < argc; i++) -            { -                DNBLogDebug("inferior_argv[%i] = '%s'", i, argv[i]); -                ctx.PushArgument (argv[i]); -            } +    // We just used the 'host:port' or the '/path/file' arg... +    argc--; +    argv++; +  } + +  //  If we know we're waiting to attach, we don't need any of this other info. +  if (start_mode != eRNBRunLoopModeInferiorAttaching && +      start_mode != eRNBRunLoopModePlatformMode) { +    if (argc == 0 || g_lockdown_opt) { +      if (g_lockdown_opt != 0) { +        // Work around for SIGPIPE crashes due to posix_spawn issue. +        // We have to close STDOUT and STDERR, else the first time we +        // try and do any, we get SIGPIPE and die as posix_spawn is +        // doing bad things with our file descriptors at the moment. +        int null = open("/dev/null", O_RDWR); +        dup2(null, STDOUT_FILENO); +        dup2(null, STDERR_FILENO); +      } else if (g_applist_opt != 0) { +        // List all applications we are able to see +        std::string applist_plist; +        int err = ListApplications(applist_plist, false, false); +        if (err == 0) { +          fputs(applist_plist.c_str(), stdout); +        } else { +          RNBLogSTDERR("error: ListApplications returned error %i\n", err);          } +        // Exit with appropriate error if we were asked to list the applications +        // with no other args were given (and we weren't trying to do this over +        // lockdown) +        return err; +      } + +      DNBLogDebug("Get args from remote protocol..."); +      start_mode = eRNBRunLoopModeGetStartModeFromRemoteProtocol; +    } else { +      start_mode = eRNBRunLoopModeInferiorLaunching; +      // Fill in the argv array in the context from the rest of our args. +      // Skip the name of this executable and the port number +      for (int i = 0; i < argc; i++) { +        DNBLogDebug("inferior_argv[%i] = '%s'", i, argv[i]); +        ctx.PushArgument(argv[i]); +      }      } +  } -    if (start_mode == eRNBRunLoopModeExit) -        return -1; +  if (start_mode == eRNBRunLoopModeExit) +    return -1; -    RNBRunLoopMode mode = start_mode; -    char err_str[1024] = {'\0'}; +  RNBRunLoopMode mode = start_mode; +  char err_str[1024] = {'\0'}; -    while (mode != eRNBRunLoopModeExit) -    { -        switch (mode) -        { -            case eRNBRunLoopModeGetStartModeFromRemoteProtocol: +  while (mode != eRNBRunLoopModeExit) { +    switch (mode) { +    case eRNBRunLoopModeGetStartModeFromRemoteProtocol:  #ifdef WITH_LOCKDOWN -                if (g_lockdown_opt) -                { -                    if (!remote->Comm().IsConnected()) -                    { -                        if (remote->Comm().ConnectToService () != rnb_success) -                        { -                            RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n"); -                            mode = eRNBRunLoopModeExit; -                        } -                        else if (g_applist_opt != 0) -                        { -                            // List all applications we are able to see -                            std::string applist_plist; -                            if (ListApplications(applist_plist, false, false) == 0) -                            { -                                DNBLogDebug("Task list: %s", applist_plist.c_str()); - -                                remote->Comm().Write(applist_plist.c_str(), applist_plist.size()); -                                // Issue a read that will never yield any data until the other side -                                // closes the socket so this process doesn't just exit and cause the -                                // socket to close prematurely on the other end and cause data loss. -                                std::string buf; -                                remote->Comm().Read(buf); -                            } -                            remote->Comm().Disconnect(false); -                            mode = eRNBRunLoopModeExit; -                            break; -                        } -                        else -                        { -                            // Start watching for remote packets -                            remote->StartReadRemoteDataThread(); -                        } -                    } -                } -                else +      if (g_lockdown_opt) { +        if (!remote->Comm().IsConnected()) { +          if (remote->Comm().ConnectToService() != rnb_success) { +            RNBLogSTDERR( +                "Failed to get connection from a remote gdb process.\n"); +            mode = eRNBRunLoopModeExit; +          } else if (g_applist_opt != 0) { +            // List all applications we are able to see +            std::string applist_plist; +            if (ListApplications(applist_plist, false, false) == 0) { +              DNBLogDebug("Task list: %s", applist_plist.c_str()); + +              remote->Comm().Write(applist_plist.c_str(), applist_plist.size()); +              // Issue a read that will never yield any data until the other +              // side +              // closes the socket so this process doesn't just exit and cause +              // the +              // socket to close prematurely on the other end and cause data +              // loss. +              std::string buf; +              remote->Comm().Read(buf); +            } +            remote->Comm().Disconnect(false); +            mode = eRNBRunLoopModeExit; +            break; +          } else { +            // Start watching for remote packets +            remote->StartReadRemoteDataThread(); +          } +        } +      } else  #endif -                if (port != INT32_MAX) -                { -                    if (!ConnectRemote (remote, host.c_str(), port, reverse_connect, named_pipe_path.c_str(), unix_socket_name.c_str())) -                        mode = eRNBRunLoopModeExit; -                } -                else if (str[0] == '/') -                { -                    if (remote->Comm().OpenFile (str)) -                        mode = eRNBRunLoopModeExit; -                } - -                if (mode != eRNBRunLoopModeExit) -                { -                    RNBLogSTDOUT ("Got a connection, waiting for process information for launching or attaching.\n"); - -                    mode = RNBRunLoopGetStartModeFromRemote (remote); -                } -                break; - -            case eRNBRunLoopModeInferiorAttaching: -                if (!waitfor_pid_name.empty()) -                { -                    // Set our end wait time if we are using a waitfor-duration -                    // option that may have been specified -                    struct timespec attach_timeout_abstime, *timeout_ptr = NULL; -                    if (waitfor_duration != 0) -                    { -                        DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, 0); -                        timeout_ptr = &attach_timeout_abstime; -                    } -                    nub_launch_flavor_t launch_flavor = g_launch_flavor; -                    if (launch_flavor == eLaunchFlavorDefault) -                    { -                        // Our default launch method is posix spawn -                        launch_flavor = eLaunchFlavorPosixSpawn; +          if (port != INT32_MAX) { +        if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, +                           named_pipe_path.c_str(), unix_socket_name.c_str())) +          mode = eRNBRunLoopModeExit; +      } else if (str[0] == '/') { +        if (remote->Comm().OpenFile(str)) +          mode = eRNBRunLoopModeExit; +      } else if (communication_fd >= 0) { +        // We were passed a file descriptor to use during fork/exec that is +        // already open +        // in our process, so lets just use it! +        if (remote->Comm().useFD(communication_fd)) +          mode = eRNBRunLoopModeExit; +        else +          remote->StartReadRemoteDataThread(); +      } + +      if (mode != eRNBRunLoopModeExit) { +        RNBLogSTDOUT("Got a connection, waiting for process information for " +                     "launching or attaching.\n"); + +        mode = RNBRunLoopGetStartModeFromRemote(remote); +      } +      break; + +    case eRNBRunLoopModeInferiorAttaching: +      if (!waitfor_pid_name.empty()) { +        // Set our end wait time if we are using a waitfor-duration +        // option that may have been specified +        struct timespec attach_timeout_abstime, *timeout_ptr = NULL; +        if (waitfor_duration != 0) { +          DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, +                                    0); +          timeout_ptr = &attach_timeout_abstime; +        } +        nub_launch_flavor_t launch_flavor = g_launch_flavor; +        if (launch_flavor == eLaunchFlavorDefault) { +          // Our default launch method is posix spawn +          launch_flavor = eLaunchFlavorPosixSpawn;  #if defined WITH_FBS -                        // Check if we have an app bundle, if so launch using SpringBoard. -                        if (waitfor_pid_name.find (".app") != std::string::npos) -                        { -                            launch_flavor = eLaunchFlavorFBS; -                        } +          // Check if we have an app bundle, if so launch using SpringBoard. +          if (waitfor_pid_name.find(".app") != std::string::npos) { +            launch_flavor = eLaunchFlavorFBS; +          }  #elif defined WITH_BKS -                        // Check if we have an app bundle, if so launch using SpringBoard. -                        if (waitfor_pid_name.find (".app") != std::string::npos) -                        { -                            launch_flavor = eLaunchFlavorBKS; -                        } +          // Check if we have an app bundle, if so launch using SpringBoard. +          if (waitfor_pid_name.find(".app") != std::string::npos) { +            launch_flavor = eLaunchFlavorBKS; +          }  #elif defined WITH_SPRINGBOARD -                        // Check if we have an app bundle, if so launch using SpringBoard. -                        if (waitfor_pid_name.find (".app") != std::string::npos) -                        { -                            launch_flavor = eLaunchFlavorSpringBoard; -                        } +          // Check if we have an app bundle, if so launch using SpringBoard. +          if (waitfor_pid_name.find(".app") != std::string::npos) { +            launch_flavor = eLaunchFlavorSpringBoard; +          }  #endif -                    } - -                    ctx.SetLaunchFlavor(launch_flavor); -                    bool ignore_existing = false; -                    RNBLogSTDOUT ("Waiting to attach to process %s...\n", waitfor_pid_name.c_str()); -                    nub_process_t pid = DNBProcessAttachWait (waitfor_pid_name.c_str(), launch_flavor, ignore_existing, timeout_ptr, waitfor_interval, err_str, sizeof(err_str)); -                    g_pid = pid; - -                    if (pid == INVALID_NUB_PROCESS) -                    { -                        ctx.LaunchStatus().SetError(-1, DNBError::Generic); -                        if (err_str[0]) -                            ctx.LaunchStatus().SetErrorString(err_str); -                        RNBLogSTDERR ("error: failed to attach to process named: \"%s\" %s\n", waitfor_pid_name.c_str(), err_str); -                        mode = eRNBRunLoopModeExit; -                    } -                    else -                    { -                        ctx.SetProcessID(pid); -                        mode = eRNBRunLoopModeInferiorExecuting; -                    } -                } -                else if (attach_pid != INVALID_NUB_PROCESS) -                { - -                    RNBLogSTDOUT ("Attaching to process %i...\n", attach_pid); -                    nub_process_t attached_pid; -                    mode = RNBRunLoopLaunchAttaching (remote, attach_pid, attached_pid); -                    if (mode != eRNBRunLoopModeInferiorExecuting) -                    { -                        const char *error_str = remote->Context().LaunchStatus().AsString(); -                        RNBLogSTDERR ("error: failed to attach process %i: %s\n", attach_pid, error_str ? error_str : "unknown error."); -                        mode = eRNBRunLoopModeExit; -                    } -                } -                else if (!attach_pid_name.empty ()) -                { -                    struct timespec attach_timeout_abstime, *timeout_ptr = NULL; -                    if (waitfor_duration != 0) -                    { -                        DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, 0); -                        timeout_ptr = &attach_timeout_abstime; -                    } - -                    RNBLogSTDOUT ("Attaching to process %s...\n", attach_pid_name.c_str()); -                    nub_process_t pid = DNBProcessAttachByName (attach_pid_name.c_str(), timeout_ptr, err_str, sizeof(err_str)); -                    g_pid = pid; -                    if (pid == INVALID_NUB_PROCESS) -                    { -                        ctx.LaunchStatus().SetError(-1, DNBError::Generic); -                        if (err_str[0]) -                            ctx.LaunchStatus().SetErrorString(err_str); -                        RNBLogSTDERR ("error: failed to attach to process named: \"%s\" %s\n", waitfor_pid_name.c_str(), err_str); -                        mode = eRNBRunLoopModeExit; -                    } -                    else -                    { -                        ctx.SetProcessID(pid); -                        mode = eRNBRunLoopModeInferiorExecuting; -                    } - -                } -                else -                { -                    RNBLogSTDERR ("error: asked to attach with empty name and invalid PID.\n"); -                    mode = eRNBRunLoopModeExit; -                } - -                if (mode != eRNBRunLoopModeExit) -                { -                    if (port != INT32_MAX) -                    { -                        if (!ConnectRemote (remote, host.c_str(), port, reverse_connect, named_pipe_path.c_str(), unix_socket_name.c_str())) -                            mode = eRNBRunLoopModeExit; -                    } -                    else if (str[0] == '/') -                    { -                        if (remote->Comm().OpenFile (str)) -                            mode = eRNBRunLoopModeExit; -                    } -                    if (mode != eRNBRunLoopModeExit) -                        RNBLogSTDOUT ("Waiting for debugger instructions for process %d.\n", attach_pid); -                } -                break; - -            case eRNBRunLoopModeInferiorLaunching: -                { -                    mode = RNBRunLoopLaunchInferior (remote, -                                                     ctx.GetSTDINPath(), -                                                     ctx.GetSTDOUTPath(), -                                                     ctx.GetSTDERRPath(), -                                                     no_stdio); - -                    if (mode == eRNBRunLoopModeInferiorExecuting) -                    { -                        if (port != INT32_MAX) -                        { -                            if (!ConnectRemote (remote, host.c_str(), port, reverse_connect, named_pipe_path.c_str(), unix_socket_name.c_str())) -                                mode = eRNBRunLoopModeExit; -                        } -                        else if (str[0] == '/') -                        { -                            if (remote->Comm().OpenFile (str)) -                                mode = eRNBRunLoopModeExit; -                        } - -                        if (mode != eRNBRunLoopModeExit) -                        { -                            const char *proc_name = "<unknown>"; -                            if (ctx.ArgumentCount() > 0) -                                proc_name = ctx.ArgumentAtIndex(0); -                            RNBLogSTDOUT ("Got a connection, launched process %s (pid = %d).\n", proc_name, ctx.ProcessID()); -                        } -                    } -                    else -                    { -                        const char *error_str = remote->Context().LaunchStatus().AsString(); -                        RNBLogSTDERR ("error: failed to launch process %s: %s\n", argv_sub_zero, error_str ? error_str : "unknown error."); -                    } -                } -                break; - -            case eRNBRunLoopModeInferiorExecuting: -                mode = RNBRunLoopInferiorExecuting(remote); -                break; - -            case eRNBRunLoopModePlatformMode: -                if (port != INT32_MAX) -                { -                    if (!ConnectRemote (remote, host.c_str(), port, reverse_connect, named_pipe_path.c_str(), unix_socket_name.c_str())) -                        mode = eRNBRunLoopModeExit; -                } -                else if (str[0] == '/') -                { -                    if (remote->Comm().OpenFile (str)) -                        mode = eRNBRunLoopModeExit; -                } - -                if (mode != eRNBRunLoopModeExit) -                    mode = RNBRunLoopPlatform (remote); -                break; - -            default: -                mode = eRNBRunLoopModeExit; -            case eRNBRunLoopModeExit: -                break;          } + +        ctx.SetLaunchFlavor(launch_flavor); +        bool ignore_existing = false; +        RNBLogSTDOUT("Waiting to attach to process %s...\n", +                     waitfor_pid_name.c_str()); +        nub_process_t pid = DNBProcessAttachWait( +            waitfor_pid_name.c_str(), launch_flavor, ignore_existing, +            timeout_ptr, waitfor_interval, err_str, sizeof(err_str)); +        g_pid = pid; + +        if (pid == INVALID_NUB_PROCESS) { +          ctx.LaunchStatus().SetError(-1, DNBError::Generic); +          if (err_str[0]) +            ctx.LaunchStatus().SetErrorString(err_str); +          RNBLogSTDERR("error: failed to attach to process named: \"%s\" %s\n", +                       waitfor_pid_name.c_str(), err_str); +          mode = eRNBRunLoopModeExit; +        } else { +          ctx.SetProcessID(pid); +          mode = eRNBRunLoopModeInferiorExecuting; +        } +      } else if (attach_pid != INVALID_NUB_PROCESS) { + +        RNBLogSTDOUT("Attaching to process %i...\n", attach_pid); +        nub_process_t attached_pid; +        mode = RNBRunLoopLaunchAttaching(remote, attach_pid, attached_pid); +        if (mode != eRNBRunLoopModeInferiorExecuting) { +          const char *error_str = remote->Context().LaunchStatus().AsString(); +          RNBLogSTDERR("error: failed to attach process %i: %s\n", attach_pid, +                       error_str ? error_str : "unknown error."); +          mode = eRNBRunLoopModeExit; +        } +      } else if (!attach_pid_name.empty()) { +        struct timespec attach_timeout_abstime, *timeout_ptr = NULL; +        if (waitfor_duration != 0) { +          DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, +                                    0); +          timeout_ptr = &attach_timeout_abstime; +        } + +        RNBLogSTDOUT("Attaching to process %s...\n", attach_pid_name.c_str()); +        nub_process_t pid = DNBProcessAttachByName( +            attach_pid_name.c_str(), timeout_ptr, err_str, sizeof(err_str)); +        g_pid = pid; +        if (pid == INVALID_NUB_PROCESS) { +          ctx.LaunchStatus().SetError(-1, DNBError::Generic); +          if (err_str[0]) +            ctx.LaunchStatus().SetErrorString(err_str); +          RNBLogSTDERR("error: failed to attach to process named: \"%s\" %s\n", +                       waitfor_pid_name.c_str(), err_str); +          mode = eRNBRunLoopModeExit; +        } else { +          ctx.SetProcessID(pid); +          mode = eRNBRunLoopModeInferiorExecuting; +        } + +      } else { +        RNBLogSTDERR( +            "error: asked to attach with empty name and invalid PID.\n"); +        mode = eRNBRunLoopModeExit; +      } + +      if (mode != eRNBRunLoopModeExit) { +        if (port != INT32_MAX) { +          if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, +                             named_pipe_path.c_str(), unix_socket_name.c_str())) +            mode = eRNBRunLoopModeExit; +        } else if (str[0] == '/') { +          if (remote->Comm().OpenFile(str)) +            mode = eRNBRunLoopModeExit; +        } else if (communication_fd >= 0) { +          // We were passed a file descriptor to use during fork/exec that is +          // already open +          // in our process, so lets just use it! +          if (remote->Comm().useFD(communication_fd)) +            mode = eRNBRunLoopModeExit; +          else +            remote->StartReadRemoteDataThread(); +        } + +        if (mode != eRNBRunLoopModeExit) +          RNBLogSTDOUT("Waiting for debugger instructions for process %d.\n", +                       attach_pid); +      } +      break; + +    case eRNBRunLoopModeInferiorLaunching: { +      mode = RNBRunLoopLaunchInferior(remote, ctx.GetSTDINPath(), +                                      ctx.GetSTDOUTPath(), ctx.GetSTDERRPath(), +                                      no_stdio); + +      if (mode == eRNBRunLoopModeInferiorExecuting) { +        if (port != INT32_MAX) { +          if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, +                             named_pipe_path.c_str(), unix_socket_name.c_str())) +            mode = eRNBRunLoopModeExit; +        } else if (str[0] == '/') { +          if (remote->Comm().OpenFile(str)) +            mode = eRNBRunLoopModeExit; +        } else if (communication_fd >= 0) { +          // We were passed a file descriptor to use during fork/exec that is +          // already open +          // in our process, so lets just use it! +          if (remote->Comm().useFD(communication_fd)) +            mode = eRNBRunLoopModeExit; +          else +            remote->StartReadRemoteDataThread(); +        } + +        if (mode != eRNBRunLoopModeExit) { +          const char *proc_name = "<unknown>"; +          if (ctx.ArgumentCount() > 0) +            proc_name = ctx.ArgumentAtIndex(0); +          RNBLogSTDOUT("Got a connection, launched process %s (pid = %d).\n", +                       proc_name, ctx.ProcessID()); +        } +      } else { +        const char *error_str = remote->Context().LaunchStatus().AsString(); +        RNBLogSTDERR("error: failed to launch process %s: %s\n", argv_sub_zero, +                     error_str ? error_str : "unknown error."); +      } +    } break; + +    case eRNBRunLoopModeInferiorExecuting: +      mode = RNBRunLoopInferiorExecuting(remote); +      break; + +    case eRNBRunLoopModePlatformMode: +      if (port != INT32_MAX) { +        if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, +                           named_pipe_path.c_str(), unix_socket_name.c_str())) +          mode = eRNBRunLoopModeExit; +      } else if (str[0] == '/') { +        if (remote->Comm().OpenFile(str)) +          mode = eRNBRunLoopModeExit; +      } else if (communication_fd >= 0) { +        // We were passed a file descriptor to use during fork/exec that is +        // already open +        // in our process, so lets just use it! +        if (remote->Comm().useFD(communication_fd)) +          mode = eRNBRunLoopModeExit; +        else +          remote->StartReadRemoteDataThread(); +      } + +      if (mode != eRNBRunLoopModeExit) +        mode = RNBRunLoopPlatform(remote); +      break; + +    default: +      mode = eRNBRunLoopModeExit; +    case eRNBRunLoopModeExit: +      break;      } +  } -    remote->StopReadRemoteDataThread (); -    remote->Context().SetProcessID(INVALID_NUB_PROCESS); -    RNBLogSTDOUT ("Exiting.\n"); +  remote->StopReadRemoteDataThread(); +  remote->Context().SetProcessID(INVALID_NUB_PROCESS); +  RNBLogSTDOUT("Exiting.\n"); -    return 0; +  return 0;  } | 
