summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2011-04-12 05:54:46 +0000
committerGreg Clayton <gclayton@apple.com>2011-04-12 05:54:46 +0000
commit8b82f087a0499319640f5d06498f965fa0214c72 (patch)
tree561c493dbe3e1a176d4c1b4ddd0c0afb396d3bea /lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
parentf52718899fa93f19403336355bca8117321ee834 (diff)
downloadbcm5719-llvm-8b82f087a0499319640f5d06498f965fa0214c72.tar.gz
bcm5719-llvm-8b82f087a0499319640f5d06498f965fa0214c72.zip
Moved the execution context that was in the Debugger into
the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp289
1 files changed, 68 insertions, 221 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index ec07fbee072..79f77e219d1 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -114,16 +114,13 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
Process (target, listener),
m_flags (0),
m_stdio_mutex (Mutex::eMutexTypeRecursive),
- m_gdb_comm(),
+ m_gdb_comm(false),
m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
m_debugserver_thread (LLDB_INVALID_HOST_THREAD),
m_last_stop_packet (),
m_register_info (),
m_async_broadcaster ("lldb.process.gdb-remote.async-broadcaster"),
m_async_thread (LLDB_INVALID_HOST_THREAD),
- m_curr_tid (LLDB_INVALID_THREAD_ID),
- m_curr_tid_run (LLDB_INVALID_THREAD_ID),
- m_z0_supported (1),
m_continue_c_tids (),
m_continue_C_tids (),
m_continue_s_tids (),
@@ -430,7 +427,6 @@ ProcessGDBRemote::DoLaunch
ObjectFile * object_file = module->GetObjectFile();
if (object_file)
{
- ArchSpec inferior_arch(module->GetArchitecture());
char host_port[128];
snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
char connect_url[128];
@@ -439,13 +435,7 @@ ProcessGDBRemote::DoLaunch
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
- error = StartDebugserverProcess (host_port,
- NULL,
- NULL,
- LLDB_INVALID_PROCESS_ID,
- NULL,
- false,
- inferior_arch);
+ error = StartDebugserverProcess (host_port);
if (error.Fail())
return error;
@@ -700,8 +690,6 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
Error error;
// Clear out and clean up from any current state
Clear();
- const ArchSpec &arch_spec = GetTarget().GetArchitecture();
-
if (attach_pid != LLDB_INVALID_PROCESS_ID)
{
// Make sure we aren't already connected?
@@ -712,13 +700,7 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
char connect_url[128];
snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
- error = StartDebugserverProcess (host_port, // debugserver_url
- NULL, // inferior_argv
- NULL, // inferior_envp
- LLDB_INVALID_PROCESS_ID, // Don't send any attach to pid options to debugserver
- NULL, // Don't send any attach by process name option to debugserver
- false, // Don't send any attach wait_for_launch flag as an option to debugserver
- arch_spec);
+ error = StartDebugserverProcess (host_port);
if (error.Fail())
{
@@ -778,21 +760,12 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
-
- const ArchSpec &arch_spec = GetTarget().GetArchitecture();
-
char host_port[128];
snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
char connect_url[128];
snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
- error = StartDebugserverProcess (host_port, // debugserver_url
- NULL, // inferior_argv
- NULL, // inferior_envp
- LLDB_INVALID_PROCESS_ID, // Don't send any attach to pid options to debugserver
- NULL, // Don't send any attach by process name option to debugserver
- false, // Don't send any attach wait_for_launch flag as an option to debugserver
- arch_spec);
+ error = StartDebugserverProcess (host_port);
if (error.Fail())
{
const char *error_string = error.AsCString();
@@ -925,7 +898,7 @@ ProcessGDBRemote::DoResume ()
if (num_continue_c_tids == num_threads)
{
// All threads are resuming...
- SetCurrentGDBRemoteThreadForRun (-1);
+ m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.PutChar ('c');
}
else if (num_continue_c_tids == 1 &&
@@ -934,7 +907,7 @@ ProcessGDBRemote::DoResume ()
num_continue_S_tids == 0 )
{
// Only one thread is continuing
- SetCurrentGDBRemoteThreadForRun (m_continue_c_tids.front());
+ m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
continue_packet.PutChar ('c');
}
else
@@ -960,7 +933,7 @@ ProcessGDBRemote::DoResume ()
if (!continue_packet_error)
{
// Add threads continuing with the same signo...
- SetCurrentGDBRemoteThreadForRun (-1);
+ m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.Printf("C%2.2x", continue_signo);
}
}
@@ -970,7 +943,7 @@ ProcessGDBRemote::DoResume ()
num_continue_S_tids == 0 )
{
// Only one thread is continuing with signal
- SetCurrentGDBRemoteThreadForRun (m_continue_C_tids.front().first);
+ m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first);
continue_packet.Printf("C%2.2x", m_continue_C_tids.front().second);
}
else
@@ -985,7 +958,7 @@ ProcessGDBRemote::DoResume ()
if (num_continue_s_tids == num_threads)
{
// All threads are resuming...
- SetCurrentGDBRemoteThreadForRun (-1);
+ m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.PutChar ('s');
}
else if (num_continue_c_tids == 0 &&
@@ -994,7 +967,7 @@ ProcessGDBRemote::DoResume ()
num_continue_S_tids == 0 )
{
// Only one thread is stepping
- SetCurrentGDBRemoteThreadForRun (m_continue_s_tids.front());
+ m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
continue_packet.PutChar ('s');
}
else
@@ -1021,7 +994,7 @@ ProcessGDBRemote::DoResume ()
if (!continue_packet_error)
{
// Add threads stepping with the same signo...
- SetCurrentGDBRemoteThreadForRun (-1);
+ m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.Printf("S%2.2x", step_signo);
}
}
@@ -1031,7 +1004,7 @@ ProcessGDBRemote::DoResume ()
num_continue_S_tids == 1 )
{
// Only one thread is stepping with signal
- SetCurrentGDBRemoteThreadForRun (m_continue_S_tids.front().first);
+ m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first);
continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
}
else
@@ -1667,40 +1640,28 @@ ProcessGDBRemote::EnableBreakpoint (BreakpointSite *bp_site)
{
// Try and set hardware breakpoint, and if that fails, fall through
// and set a software breakpoint?
- }
-
- if (m_z0_supported)
- {
- char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "Z0,%llx,%zx", addr, bp_op_size);
- assert (packet_len + 1 < sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
+ if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointHardware))
{
- if (response.IsUnsupportedResponse())
- {
- // Disable z packet support and try again
- m_z0_supported = 0;
- return EnableBreakpoint (bp_site);
- }
- else if (response.IsOKResponse())
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0)
{
bp_site->SetEnabled(true);
- bp_site->SetType (BreakpointSite::eExternal);
+ bp_site->SetType (BreakpointSite::eHardware);
return error;
}
- else
- {
- uint8_t error_byte = response.GetError();
- if (error_byte)
- error.SetErrorStringWithFormat("%x packet failed with error: %i (0x%2.2x).\n", packet, error_byte, error_byte);
- }
}
}
- else
+
+ if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
{
- return EnableSoftwareBreakpoint (bp_site);
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
+ {
+ bp_site->SetEnabled(true);
+ bp_site->SetType (BreakpointSite::eExternal);
+ return error;
+ }
}
+
+ return EnableSoftwareBreakpoint (bp_site);
}
if (log)
@@ -1731,44 +1692,25 @@ ProcessGDBRemote::DisableBreakpoint (BreakpointSite *bp_site)
{
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
- if (bp_site->IsHardware())
- {
- // TODO: disable hardware breakpoint...
- }
- else
+ BreakpointSite::Type bp_type = bp_site->GetType();
+ switch (bp_type)
{
- if (m_z0_supported)
- {
- char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "z0,%llx,%zx", addr, bp_op_size);
- assert (packet_len + 1 < sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
- {
- if (response.IsUnsupportedResponse())
- {
- error.SetErrorString("Breakpoint site was set with Z packet, yet remote debugserver states z packets are not supported.");
- }
- else if (response.IsOKResponse())
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS", site_id, (uint64_t)addr);
- bp_site->SetEnabled(false);
- return error;
- }
- else
- {
- uint8_t error_byte = response.GetError();
- if (error_byte)
- error.SetErrorStringWithFormat("%x packet failed with error: %i (0x%2.2x).\n", packet, error_byte, error_byte);
- }
- }
- }
- else
- {
- return DisableSoftwareBreakpoint (bp_site);
- }
+ case BreakpointSite::eSoftware:
+ error = DisableSoftwareBreakpoint (bp_site);
+ break;
+
+ case BreakpointSite::eHardware:
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+ error.SetErrorToGenericError();
+ break;
+
+ case BreakpointSite::eExternal:
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+ error.SetErrorToGenericError();
+ break;
}
+ if (error.Success())
+ bp_site->SetEnabled(false);
}
else
{
@@ -1869,16 +1811,7 @@ ProcessGDBRemote::DoSignal (int signo)
}
Error
-ProcessGDBRemote::StartDebugserverProcess
-(
- const char *debugserver_url, // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
- char const *inferior_argv[], // Arguments for the inferior program including the path to the inferior itself as the first argument
- char const *inferior_envp[], // Environment to pass along to the inferior program
- lldb::pid_t attach_pid, // If inferior inferior_argv == NULL, and attach_pid != LLDB_INVALID_PROCESS_ID send this pid as an argument to debugserver
- const char *attach_name, // Wait for the next process to launch whose basename matches "attach_name"
- bool wait_for_launch, // Wait for the process named "attach_name" to launch
- const ArchSpec& inferior_arch // The arch of the inferior that we will launch
-)
+ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url) // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
{
Error error;
if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
@@ -1886,8 +1819,9 @@ ProcessGDBRemote::StartDebugserverProcess
// If we locate debugserver, keep that located version around
static FileSpec g_debugserver_file_spec;
- FileSpec debugserver_file_spec;
+ ProcessLaunchInfo launch_info;
char debugserver_path[PATH_MAX];
+ FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
// Always check to see if we have an environment override for the path
// to the debugserver to use and use it if we do.
@@ -1922,25 +1856,10 @@ ProcessGDBRemote::StartDebugserverProcess
debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
m_stdio_communication.Clear();
- posix_spawnattr_t attr;
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- Error local_err; // Errors that don't affect the spawning.
- if (log)
- log->Printf ("%s ( path='%s', argv=%p, envp=%p, arch=%s )",
- __FUNCTION__,
- debugserver_path,
- inferior_argv,
- inferior_envp,
- inferior_arch.GetArchitectureName());
- error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
- if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawnattr_init ( &attr )");
- if (error.Fail())
- return error;
-
- Args debugserver_args;
+ Args &debugserver_args = launch_info.GetArguments();
char arg_cstr[PATH_MAX];
// Start args with "debugserver /file/path -r --"
@@ -1968,6 +1887,12 @@ ProcessGDBRemote::StartDebugserverProcess
// debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
// debugserver_args.AppendArgument("--log-flags=0x802e0e");
+ // We currently send down all arguments, attach pids, or attach
+ // process names in dedicated GDB server packets, so we don't need
+ // to pass them as arguments. This is currently because of all the
+ // things we need to setup prior to launching: the environment,
+ // current working dir, file actions, etc.
+#if 0
// Now append the program arguments
if (inferior_argv)
{
@@ -1990,20 +1915,18 @@ ProcessGDBRemote::StartDebugserverProcess
debugserver_args.AppendArgument ("--attach");
debugserver_args.AppendArgument (attach_name);
}
-
- Error file_actions_err;
- posix_spawn_file_actions_t file_actions;
-#if DONT_CLOSE_DEBUGSERVER_STDIO
- file_actions_err.SetErrorString ("Remove this after uncommenting the code block below.");
-#else
- file_actions_err.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
- if (file_actions_err.Success())
- {
- ::posix_spawn_file_actions_addclose (&file_actions, STDIN_FILENO);
- ::posix_spawn_file_actions_addclose (&file_actions, STDOUT_FILENO);
- ::posix_spawn_file_actions_addclose (&file_actions, STDERR_FILENO);
- }
#endif
+
+ ProcessLaunchInfo::FileAction file_action;
+
+ // Close STDIN, STDOUT and STDERR. We might need to redirect them
+ // to "/dev/null" if we run into any problems.
+ file_action.Close (STDIN_FILENO);
+ launch_info.AppendFileAction (file_action);
+ file_action.Close (STDOUT_FILENO);
+ launch_info.AppendFileAction (file_action);
+ file_action.Close (STDERR_FILENO);
+ launch_info.AppendFileAction (file_action);
if (log)
{
@@ -2012,28 +1935,15 @@ ProcessGDBRemote::StartDebugserverProcess
log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData());
}
- error.SetError (::posix_spawnp (&m_debugserver_pid,
- debugserver_path,
- file_actions_err.Success() ? &file_actions : NULL,
- &attr,
- debugserver_args.GetArgumentVector(),
- (char * const*)inferior_envp),
- eErrorTypePOSIX);
-
-
- ::posix_spawnattr_destroy (&attr);
-
- if (file_actions_err.Success())
- ::posix_spawn_file_actions_destroy (&file_actions);
+ error = Host::LaunchProcess(launch_info);
- // We have seen some cases where posix_spawnp was returning a valid
- // looking pid even when an error was returned, so clear it out
- if (error.Fail())
+ if (error.Success ())
+ m_debugserver_pid = launch_info.GetProcessID();
+ else
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", m_debugserver_pid, debugserver_path, NULL, &attr, inferior_argv, inferior_envp);
-
+ error.PutToLog(log.get(), "Host::LaunchProcess (launch_info) => pid=%i, path='%s'", m_debugserver_pid, debugserver_path);
}
else
{
@@ -2143,71 +2053,8 @@ ProcessGDBRemote::Initialize()
}
bool
-ProcessGDBRemote::SetCurrentGDBRemoteThread (int tid)
-{
- if (m_curr_tid == tid)
- return true;
-
- char packet[32];
- int packet_len;
- if (tid <= 0)
- packet_len = ::snprintf (packet, sizeof(packet), "Hg%i", tid);
- else
- packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
- assert (packet_len + 1 < sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
- {
- if (response.IsOKResponse())
- {
- m_curr_tid = tid;
- return true;
- }
- }
- return false;
-}
-
-bool
-ProcessGDBRemote::SetCurrentGDBRemoteThreadForRun (int tid)
-{
- if (m_curr_tid_run == tid)
- return true;
-
- char packet[32];
- int packet_len;
- if (tid <= 0)
- packet_len = ::snprintf (packet, sizeof(packet), "Hc%i", tid);
- else
- packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
-
- assert (packet_len + 1 < sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
- {
- if (response.IsOKResponse())
- {
- m_curr_tid_run = tid;
- return true;
- }
- }
- return false;
-}
-
-void
-ProcessGDBRemote::ResetGDBRemoteState ()
-{
- // Reset and GDB remote state
- m_curr_tid = LLDB_INVALID_THREAD_ID;
- m_curr_tid_run = LLDB_INVALID_THREAD_ID;
- m_z0_supported = 1;
-}
-
-
-bool
ProcessGDBRemote::StartAsyncThread ()
{
- ResetGDBRemoteState ();
-
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
OpenPOWER on IntegriCloud