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