Fixed CommandReturnObject::SetImmediateErrorFile() to set the correct stream.
Modifed lldb_private::Process to be able to handle connecting to a remote
target that isn't running a process. This leaves lldb_private::Process in the
eStateConnected state from which we can then do an attach or launch.
Modified ProcessGDBRemote to be able to set stdin, stdout, stderr, working
dir, disable ASLR and a few other settings down by using new GDB remote
packets. This allows us to keep all of our current launch flags and settings
intact and still be able to communicate them over to the remote GDB server.
Previously these were being sent as arguments to the debugserver binary that
we were spawning. Also modified ProcessGDBRemote to handle losing connection
to the remote GDB server and always exit immediately. We do this by watching
the lldb_private::Communication event bit for the read thread exiting in the
ProcessGDBRemote async thread.
Added support for many of the new 'Q' packets for setting stdin, stdout,
stderr, working dir and disable ASLR to the GDBRemoteCommunication class for
easy accesss.
Modified debugserver for all of the new 'Q' packets and also made it so that
debugserver always exists if it loses connection with the remote debugger.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@126444 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/debugserver/source/DNB.cpp b/tools/debugserver/source/DNB.cpp
index fab4741..6354427 100644
--- a/tools/debugserver/source/DNB.cpp
+++ b/tools/debugserver/source/DNB.cpp
@@ -1971,6 +1971,16 @@
return 0;
}
+uint32_t
+DNBProcessGetCPUType (nub_process_t pid)
+{
+ MachProcessSP procSP;
+ if (GetProcessSP (pid, procSP))
+ return procSP->GetCPUType ();
+ return 0;
+
+}
+
nub_bool_t
DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size)
{
diff --git a/tools/debugserver/source/DNB.h b/tools/debugserver/source/DNB.h
index 2b2389d..e9a3f34 100644
--- a/tools/debugserver/source/DNB.h
+++ b/tools/debugserver/source/DNB.h
@@ -86,6 +86,7 @@
nub_size_t DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size) DNB_EXPORT;
nub_size_t DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size) DNB_EXPORT;
nub_size_t DNBProcessGetStopCount (nub_process_t pid) DNB_EXPORT;
+uint32_t DNBProcessGetCPUType (nub_process_t pid) DNB_EXPORT;
//----------------------------------------------------------------------
// Process executable and arguments
//----------------------------------------------------------------------
diff --git a/tools/debugserver/source/DNBArch.cpp b/tools/debugserver/source/DNBArch.cpp
index 1174391..f56c6a3 100644
--- a/tools/debugserver/source/DNBArch.cpp
+++ b/tools/debugserver/source/DNBArch.cpp
@@ -21,10 +21,12 @@
typedef std::map<uint32_t, DNBArchPluginInfo> CPUPluginInfoMap;
-#if defined (__i386__)
-static uint32_t g_current_cpu_type = CPU_TYPE_I386;
-#elif defined (__x86_64__)
-static uint32_t g_current_cpu_type = CPU_TYPE_X86_64;
+//#if defined (__i386__)
+//static uint32_t g_current_cpu_type = CPU_TYPE_I386;
+//#elif defined (__x86_64__)
+//static uint32_t g_current_cpu_type = CPU_TYPE_X86_64;
+#if defined (__i386__) || defined (__x86_64__)
+static uint32_t g_current_cpu_type = 0;
#elif defined (__arm__)
static uint32_t g_current_cpu_type = CPU_TYPE_ARM;
#else
diff --git a/tools/debugserver/source/MacOSX/MachProcess.cpp b/tools/debugserver/source/MacOSX/MachProcess.cpp
index 12c981b..1c002c2 100644
--- a/tools/debugserver/source/MacOSX/MachProcess.cpp
+++ b/tools/debugserver/source/MacOSX/MachProcess.cpp
@@ -18,6 +18,7 @@
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
+#include <sys/sysctl.h>
#include <unistd.h>
#include "MacOSX/CFUtils.h"
#include "SysSignal.h"
@@ -91,6 +92,7 @@
MachProcess::MachProcess() :
m_pid (0),
+ m_cpu_type (0),
m_child_stdin (-1),
m_child_stdout (-1),
m_child_stderr (-1),
@@ -200,6 +202,14 @@
return m_thread_list.GetThreadInfo(tid);
}
+uint32_t
+MachProcess::GetCPUType ()
+{
+ if (m_cpu_type == 0 && m_pid != 0)
+ m_cpu_type = MachProcess::GetCPUTypeForLocalProcess (m_pid);
+ return m_cpu_type;
+}
+
const DNBRegisterSetInfo *
MachProcess::GetRegisterSetInfo (nub_thread_t tid, nub_size_t *num_reg_sets) const
{
@@ -1662,14 +1672,16 @@
// We don't need to do this for ARM, and we really shouldn't now that we
// have multiple CPU subtypes and no posix_spawnattr call that allows us
// to set which CPU subtype to launch...
- size_t ocount = 0;
- err.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), DNBError::POSIX);
- if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %zu )", cpu_type, ocount);
+ if (cpu_type != 0)
+ {
+ size_t ocount = 0;
+ err.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), DNBError::POSIX);
+ if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
+ err.LogThreaded("::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %zu )", cpu_type, ocount);
- if (err.Fail() != 0 || ocount != 1)
- return INVALID_NUB_PROCESS;
-
+ if (err.Fail() != 0 || ocount != 1)
+ return INVALID_NUB_PROCESS;
+ }
#endif
PseudoTerminal pty;
@@ -1712,21 +1724,25 @@
}
else
{
- int slave_fd_err = open (stderr_path ? stderr_path : "/dev/null", O_NOCTTY | O_CREAT | O_RDWR , 0640);
- int slave_fd_in = open (stdin_path ? stdin_path : "/dev/null", O_NOCTTY | O_RDONLY);
- int slave_fd_out = open (stdout_path ? stdout_path : "/dev/null", O_NOCTTY | O_CREAT | O_WRONLY , 0640);
+ if ( stdin_path == NULL) stdin_path = "/dev/null";
+ if (stdout_path == NULL) stdout_path = "/dev/null";
+ if (stderr_path == NULL) stderr_path = "/dev/null";
+
+ int slave_fd_err = open (stderr_path, O_NOCTTY | O_CREAT | O_RDWR , 0640);
+ int slave_fd_in = open (stdin_path , O_NOCTTY | O_RDONLY);
+ int slave_fd_out = open (stdout_path, O_NOCTTY | O_CREAT | O_WRONLY , 0640);
err.SetError( ::posix_spawn_file_actions_adddup2(&file_actions, slave_fd_err, STDERR_FILENO), DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawn_file_actions_adddup2 ( &file_actions, filedes = %d, newfiledes = STDERR_FILENO )", slave_fd_err);
+ err.LogThreaded("::posix_spawn_file_actions_adddup2 ( &file_actions, filedes = %d (\"%s\"), newfiledes = STDERR_FILENO )", slave_fd_err, stderr_path);
err.SetError( ::posix_spawn_file_actions_adddup2(&file_actions, slave_fd_in, STDIN_FILENO), DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawn_file_actions_adddup2 ( &file_actions, filedes = %d, newfiledes = STDIN_FILENO )", slave_fd_in);
+ err.LogThreaded("::posix_spawn_file_actions_adddup2 ( &file_actions, filedes = %d (\"%s\"), newfiledes = STDIN_FILENO )", slave_fd_in, stdin_path);
err.SetError( ::posix_spawn_file_actions_adddup2(&file_actions, slave_fd_out, STDOUT_FILENO), DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
- err.LogThreaded("::posix_spawn_file_actions_adddup2 ( &file_actions, filedes = %d, newfiledes = STDOUT_FILENO )", slave_fd_out);
+ err.LogThreaded("::posix_spawn_file_actions_adddup2 ( &file_actions, filedes = %d (\"%s\"), newfiledes = STDOUT_FILENO )", slave_fd_out, stdout_path);
}
// TODO: Verify if we can set the working directory back immediately
@@ -1763,9 +1779,16 @@
process->SetChildFileDescriptors(master_fd, master_fd, master_fd);
}
}
-
::posix_spawnattr_destroy (&attr);
+ if (pid != INVALID_NUB_PROCESS)
+ {
+ cpu_type_t pid_cpu_type = MachProcess::GetCPUTypeForLocalProcess (pid);
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( ) pid=%i, cpu_type=0x%8.8x", __FUNCTION__, pid, pid_cpu_type);
+ if (pid_cpu_type)
+ DNBArchProtocol::SetArchitecture (pid_cpu_type);
+ }
+
if (file_actions_valid)
{
DNBError err2;
@@ -1777,6 +1800,24 @@
return pid;
}
+uint32_t
+MachProcess::GetCPUTypeForLocalProcess (pid_t pid)
+{
+ int mib[CTL_MAXNAME]={0,};
+ size_t len = CTL_MAXNAME;
+ if (::sysctlnametomib("sysctl.proc_cputype", mib, &len))
+ return 0;
+
+ mib[len] = pid;
+ len++;
+
+ cpu_type_t cpu;
+ size_t cpu_len = sizeof(cpu);
+ if (::sysctl (mib, len, &cpu, &cpu_len, 0, 0))
+ cpu = 0;
+ return cpu;
+}
+
pid_t
MachProcess::ForkChildForPTraceDebugging
(
diff --git a/tools/debugserver/source/MacOSX/MachProcess.h b/tools/debugserver/source/MacOSX/MachProcess.h
index 85a8b46..d52735a 100644
--- a/tools/debugserver/source/MacOSX/MachProcess.h
+++ b/tools/debugserver/source/MacOSX/MachProcess.h
@@ -58,6 +58,8 @@
nub_launch_flavor_t launch_flavor,
int disable_aslr,
DNBError &err);
+
+ static uint32_t GetCPUTypeForLocalProcess (pid_t pid);
static pid_t ForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], MachProcess* process, DNBError &err);
static pid_t PosixSpawnChildForPTraceDebugging (const char *path,
cpu_type_t cpu_type,
@@ -167,6 +169,7 @@
void DumpThreadStoppedReason(nub_thread_t tid) const;
const char * GetThreadInfo (nub_thread_t tid) const;
+ uint32_t GetCPUType ();
nub_state_t GetState ();
void SetState (nub_state_t state);
bool IsRunning (nub_state_t state)
@@ -248,6 +251,7 @@
nub_state_t DoSIGSTOP (bool clear_bps_and_wps, uint32_t *thread_idx_ptr = NULL);
pid_t m_pid; // Process ID of child process
+ cpu_type_t m_cpu_type; // The CPU type of this process
int m_child_stdin;
int m_child_stdout;
int m_child_stderr;
diff --git a/tools/debugserver/source/RNBContext.h b/tools/debugserver/source/RNBContext.h
index 93b98de..0044d19 100644
--- a/tools/debugserver/source/RNBContext.h
+++ b/tools/debugserver/source/RNBContext.h
@@ -104,12 +104,25 @@
}
bool SetWorkingDirectory (const char *path);
-
+
+ std::string& GetSTDIN () { return m_stdin; }
+ std::string& GetSTDOUT () { return m_stdout; }
+ std::string& GetSTDERR () { return m_stderr; }
+ std::string& GetWorkingDir () { return m_working_dir; }
+
+ const char * GetSTDINPath() { return m_stdin.empty() ? NULL : m_stdin.c_str(); }
+ const char * GetSTDOUTPath() { return m_stdout.empty() ? NULL : m_stdout.c_str(); }
+ const char * GetSTDERRPath() { return m_stderr.empty() ? NULL : m_stderr.c_str(); }
+ const char * GetWorkingDirPath() { return m_working_dir.empty() ? NULL : m_working_dir.c_str(); }
protected:
//------------------------------------------------------------------
// Classes that inherit from RNBContext can see and modify these
//------------------------------------------------------------------
nub_process_t m_pid;
+ std::string m_stdin;
+ std::string m_stdout;
+ std::string m_stderr;
+ std::string m_working_dir;
nub_size_t m_pid_stop_count;
PThreadEvent m_events; // Threaded events that we can wait for
pthread_t m_pid_pthread;
diff --git a/tools/debugserver/source/RNBRemote.cpp b/tools/debugserver/source/RNBRemote.cpp
index 1d6d088..465abcb 100644
--- a/tools/debugserver/source/RNBRemote.cpp
+++ b/tools/debugserver/source/RNBRemote.cpp
@@ -17,6 +17,7 @@
#include <unistd.h>
#include <signal.h>
#include <mach/exception_types.h>
+#include <sys/stat.h>
#include <sys/sysctl.h>
#include "DNB.h"
@@ -60,10 +61,9 @@
extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
-RNBRemote::RNBRemote (bool use_native_regs, const char *arch) :
+RNBRemote::RNBRemote () :
m_ctx (),
m_comm (),
- m_arch (),
m_continue_thread(-1),
m_thread(-1),
m_mutex(),
@@ -77,12 +77,10 @@
m_extended_mode(false),
m_noack_mode(false),
m_thread_suffix_supported (false),
- m_use_native_regs (use_native_regs)
+ m_use_native_regs (false)
{
DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
CreatePacketTable ();
- if (arch && arch[0])
- m_arch.assign (arch);
}
@@ -178,6 +176,10 @@
t.push_back (Packet (set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle"));
t.push_back (Packet (set_environment_variable, &RNBRemote::HandlePacket_QEnvironment , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment"));
t.push_back (Packet (set_disable_aslr, &RNBRemote::HandlePacket_QSetDisableASLR , NULL, "QSetDisableASLR:", "Set wether to disable ASLR when launching the process with the set argv ('A') packet"));
+ t.push_back (Packet (set_stdin, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDIN:", "Set the standard input for a process to be launched with the 'A' packet"));
+ t.push_back (Packet (set_stdout, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDOUT:", "Set the standard output for a process to be launched with the 'A' packet"));
+ t.push_back (Packet (set_stderr, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDERR:", "Set the standard error for a process to be launched with the 'A' packet"));
+ t.push_back (Packet (set_working_dir, &RNBRemote::HandlePacket_QSetWorkingDir , NULL, "QSetWorkingDir:", "Set the working directory for a process to be launched with the 'A' packet"));
// t.push_back (Packet (pass_signals_to_inferior, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify which signals are passed to the inferior"));
t.push_back (Packet (allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process."));
t.push_back (Packet (deallocate_memory, &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process."));
@@ -1002,7 +1004,7 @@
if (m_use_native_regs)
{
- DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface (%s)", __FUNCTION__, m_arch.c_str());
+ DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface", __FUNCTION__);
// Discover the registers by querying the DNB interface and letting it
// state the registers that it would like to export. This allows the
// registers to be discovered using multiple qRegisterInfo calls to get
@@ -1041,9 +1043,10 @@
}
else
{
- DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting gdb registers (%s)", __FUNCTION__, m_arch.c_str());
+ uint32_t cpu_type = DNBProcessGetCPUType (pid);
+ DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting gdb registers(%s)", __FUNCTION__, m_arch.c_str());
#if defined (__i386__) || defined (__x86_64__)
- if (m_arch.compare("x86_64") == 0)
+ if (cpu_type == CPU_TYPE_X86_64)
{
const size_t num_regs = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
for (uint32_t i=0; i<num_regs; ++i)
@@ -1058,7 +1061,7 @@
g_num_reg_entries = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
return true;
}
- else if (m_arch.compare("i386") == 0)
+ else if (cpu_type == CPU_TYPE_I386)
{
const size_t num_regs = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
for (uint32_t i=0; i<num_regs; ++i)
@@ -1074,7 +1077,7 @@
return true;
}
#elif defined (__arm__)
- if (m_arch.find ("arm") == 0)
+ if (cpu_type == CPU_TYPE_ARM)
{
const size_t num_regs = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
for (uint32_t i=0; i<num_regs; ++i)
@@ -1748,6 +1751,80 @@
return SendPacket ("OK");
}
+rnb_err_t
+RNBRemote::HandlePacket_QSetSTDIO (const char *p)
+{
+ // Only set stdin/out/err if we don't already have a process
+ if (!m_ctx.HasValidProcessID())
+ {
+ bool success = false;
+ // Check the seventh character since the packet will be one of:
+ // QSetSTDIN
+ // QSetSTDOUT
+ // QSetSTDERR
+ StringExtractor packet(p);
+ packet.SetFilePos (7);
+ char ch = packet.GetChar();
+ while (packet.GetChar() != ':')
+ /* Do nothing. */;
+
+ switch (ch)
+ {
+ case 'I': // STDIN
+ packet.GetHexByteString (m_ctx.GetSTDIN());
+ success = !m_ctx.GetSTDIN().empty();
+ break;
+
+ case 'O': // STDOUT
+ packet.GetHexByteString (m_ctx.GetSTDOUT());
+ success = !m_ctx.GetSTDOUT().empty();
+ break;
+
+ case 'E': // STDERR
+ packet.GetHexByteString (m_ctx.GetSTDERR());
+ success = !m_ctx.GetSTDERR().empty();
+ break;
+
+ default:
+ break;
+ }
+ if (success)
+ return SendPacket ("OK");
+ return SendPacket ("E57");
+ }
+ return SendPacket ("E58");
+}
+
+rnb_err_t
+RNBRemote::HandlePacket_QSetWorkingDir (const char *p)
+{
+ // Only set the working directory if we don't already have a process
+ if (!m_ctx.HasValidProcessID())
+ {
+ StringExtractor packet(p += sizeof ("QSetWorkingDir:") - 1);
+ if (packet.GetHexByteString (m_ctx.GetWorkingDir()))
+ {
+ struct stat working_dir_stat;
+ if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1)
+ {
+ m_ctx.GetWorkingDir().clear();
+ return SendPacket ("E61"); // Working directory doesn't exist...
+ }
+ else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR)
+ {
+ return SendPacket ("OK");
+ }
+ else
+ {
+ m_ctx.GetWorkingDir().clear();
+ return SendPacket ("E62"); // Working directory isn't a directory...
+ }
+ }
+ return SendPacket ("E59"); // Invalid path
+ }
+ return SendPacket ("E60"); // Already had a process, too late to set working dir
+}
+
rnb_err_t
RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p)
@@ -1824,13 +1901,10 @@
void
-register_value_in_hex_fixed_width
-(
- std::ostream& ostrm,
- nub_process_t pid,
- nub_thread_t tid,
- const register_map_entry_t* reg
- )
+register_value_in_hex_fixed_width (std::ostream& ostrm,
+ nub_process_t pid,
+ nub_thread_t tid,
+ const register_map_entry_t* reg)
{
if (reg != NULL)
{
@@ -1862,13 +1936,10 @@
void
-gdb_regnum_with_fixed_width_hex_register_value
-(
- std::ostream& ostrm,
- nub_process_t pid,
- nub_thread_t tid,
- const register_map_entry_t* reg
- )
+gdb_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm,
+ nub_process_t pid,
+ nub_thread_t tid,
+ const register_map_entry_t* reg)
{
// Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
// gdb register number, and VVVVVVVV is the correct number of hex bytes
diff --git a/tools/debugserver/source/RNBRemote.h b/tools/debugserver/source/RNBRemote.h
index e3a968f..6f0e5f0 100644
--- a/tools/debugserver/source/RNBRemote.h
+++ b/tools/debugserver/source/RNBRemote.h
@@ -99,6 +99,10 @@
set_max_payload_size, // 'QSetMaxPayloadSize:'
set_environment_variable, // 'QEnvironment:'
set_disable_aslr, // 'QSetDisableASLR:'
+ set_stdin, // 'QSetSTDIN:'
+ set_stdout, // 'QSetSTDOUT:'
+ set_stderr, // 'QSetSTDERR:'
+ set_working_dir, // 'QSetWorkingDir:'
allocate_memory, // '_M'
deallocate_memory, // '_m'
@@ -107,7 +111,7 @@
typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p);
- RNBRemote (bool use_native_regs, const char *arch);
+ RNBRemote ();
~RNBRemote ();
void Initialize();
@@ -161,6 +165,8 @@
rnb_err_t HandlePacket_QThreadSuffixSupported (const char *p);
rnb_err_t HandlePacket_QSetLogging (const char *p);
rnb_err_t HandlePacket_QSetDisableASLR (const char *p);
+ rnb_err_t HandlePacket_QSetSTDIO (const char *p);
+ rnb_err_t HandlePacket_QSetWorkingDir (const char *p);
rnb_err_t HandlePacket_QSetMaxPayloadSize (const char *p);
rnb_err_t HandlePacket_QSetMaxPacketSize (const char *p);
rnb_err_t HandlePacket_QEnvironment (const char *p);
@@ -198,6 +204,11 @@
RNBContext& Context() { return m_ctx; }
RNBSocket& Comm() { return m_comm; }
+ void
+ SetUseNativeRegisters (bool b)
+ {
+ m_use_native_regs = b;
+ }
private:
// Outlaw some contructors
RNBRemote (const RNBRemote &);
diff --git a/tools/debugserver/source/debugserver.cpp b/tools/debugserver/source/debugserver.cpp
index 83131b9..8fab13f 100644
--- a/tools/debugserver/source/debugserver.cpp
+++ b/tools/debugserver/source/debugserver.cpp
@@ -74,7 +74,8 @@
if (remote)
{
RNBContext& ctx = remote->Context();
- uint32_t event_mask = RNBContext::event_read_packet_available;
+ uint32_t event_mask = RNBContext::event_read_packet_available |
+ RNBContext::event_read_thread_exiting;
// Spin waiting to get the A packet.
while (1)
@@ -83,6 +84,12 @@
nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask);
DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", __FUNCTION__, event_mask, set_events);
+ if (set_events & RNBContext::event_read_thread_exiting)
+ {
+ RNBLogSTDERR ("error: packet read thread exited.");
+ return eRNBRunLoopModeExit;
+ }
+
if (set_events & RNBContext::event_read_packet_available)
{
rnb_err_t err = rnb_err;
@@ -219,7 +226,9 @@
ctx.LaunchStatus().SetErrorString(launch_err_str);
}
else
+ {
ctx.LaunchStatus().Clear();
+ }
if (remote->Comm().IsConnected())
{
@@ -682,6 +691,18 @@
signal (SIGPIPE, signal_handler);
signal (SIGHUP, signal_handler);
+ g_remoteSP.reset (new RNBRemote ());
+
+
+ RNBRemote *remote = g_remoteSP.get();
+ if (remote == NULL)
+ {
+ RNBLogSTDERR ("error: failed to create a remote connection class\n");
+ return -1;
+ }
+
+ RNBContext& ctx = remote->Context();
+
int i;
int attach_pid = INVALID_NUB_PROCESS;
@@ -690,14 +711,10 @@
// Parse our options
int ch;
int long_option_index = 0;
- int use_native_registers = 0;
int debug = 0;
std::string compile_options;
std::string waitfor_pid_name; // Wait for a process that starts with this name
std::string attach_pid_name;
- std::string stdin_path;
- std::string stdout_path;
- std::string stderr_path;
std::string arch_name;
std::string working_dir; // The new working directory to use for the inferior
useconds_t waitfor_interval = 1000; // Time in usecs between process lists polls when waiting for a process by name, default 1 msec.
@@ -859,7 +876,7 @@
break;
case 'r':
- use_native_registers = 1;
+ remote->SetUseNativeRegisters (true);
break;
case 'v':
@@ -867,21 +884,21 @@
break;
case 's':
- stdin_path.assign(optarg);
- stdout_path.assign(optarg);
- stderr_path.assign(optarg);
+ ctx.GetSTDIN().assign(optarg);
+ ctx.GetSTDOUT().assign(optarg);
+ ctx.GetSTDERR().assign(optarg);
break;
case 'I':
- stdin_path.assign(optarg);
+ ctx.GetSTDIN().assign(optarg);
break;
case 'O':
- stdout_path.assign(optarg);
+ ctx.GetSTDOUT().assign(optarg);
break;
case 'E':
- stderr_path.assign(optarg);
+ ctx.GetSTDERR().assign(optarg);
break;
case 'n':
@@ -910,11 +927,7 @@
if (arch_name.empty())
{
-#if defined (__i386__)
- arch_name.assign ("i386");
-#elif defined (__x86_64__)
- arch_name.assign ("x86_64");
-#elif defined (__arm__)
+#if defined (__arm__)
arch_name.assign ("arm");
#endif
}
@@ -923,24 +936,15 @@
DNBSetArchitecture (arch_name.c_str());
}
- if (arch_name.empty())
- {
- fprintf(stderr, "error: no architecture was specified\n");
- exit (8);
- }
+// if (arch_name.empty())
+// {
+// fprintf(stderr, "error: no architecture was specified\n");
+// exit (8);
+// }
// Skip any options we consumed with getopt_long
argc -= optind;
argv += optind;
- g_remoteSP.reset (new RNBRemote (use_native_registers, arch_name.c_str()));
-
-
- RNBRemote *remote = g_remoteSP.get();
- if (remote == NULL)
- {
- RNBLogSTDERR ("error: failed to create a remote connection class\n");
- return -1;
- }
if (!working_dir.empty())
{
@@ -953,9 +957,6 @@
remote->Initialize();
- RNBContext& ctx = remote->Context();
-
-
// It is ok for us to set NULL as the logfile (this will disable any logging)
if (log_file != NULL)
@@ -1250,9 +1251,9 @@
case eRNBRunLoopModeInferiorLaunching:
{
mode = RNBRunLoopLaunchInferior (remote,
- stdin_path.empty() ? NULL : stdin_path.c_str(),
- stdout_path.empty() ? NULL : stdout_path.c_str(),
- stderr_path.empty() ? NULL : stderr_path.c_str(),
+ ctx.GetSTDINPath(),
+ ctx.GetSTDOUTPath(),
+ ctx.GetSTDERRPath(),
no_stdio);
if (mode == eRNBRunLoopModeInferiorExecuting)