blob: cba830ebad998fedcbd14286148790021955c0da [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- ProcessGDBRemote.cpp ------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11#include <errno.h>
Chris Lattner24943d22010-06-08 16:52:24 +000012#include <spawn.h>
Stephen Wilson50daf772011-03-25 18:16:28 +000013#include <stdlib.h>
Chris Lattner24943d22010-06-08 16:52:24 +000014#include <sys/types.h>
Chris Lattner24943d22010-06-08 16:52:24 +000015#include <sys/stat.h>
Stephen Wilson60f19d52011-03-30 00:12:40 +000016#include <time.h>
Chris Lattner24943d22010-06-08 16:52:24 +000017
18// C++ Includes
19#include <algorithm>
20#include <map>
21
22// Other libraries and framework includes
23
24#include "lldb/Breakpoint/WatchpointLocation.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000025#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000026#include "lldb/Core/ArchSpec.h"
27#include "lldb/Core/Debugger.h"
28#include "lldb/Core/ConnectionFileDescriptor.h"
Greg Clayton5f54ac32011-02-08 05:05:52 +000029#include "lldb/Host/FileSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000030#include "lldb/Core/InputReader.h"
31#include "lldb/Core/Module.h"
32#include "lldb/Core/PluginManager.h"
33#include "lldb/Core/State.h"
34#include "lldb/Core/StreamString.h"
35#include "lldb/Core/Timer.h"
36#include "lldb/Host/TimeValue.h"
37#include "lldb/Symbol/ObjectFile.h"
38#include "lldb/Target/DynamicLoader.h"
39#include "lldb/Target/Target.h"
40#include "lldb/Target/TargetList.h"
Jason Molendadea5ea72010-06-09 21:28:42 +000041#include "lldb/Utility/PseudoTerminal.h"
Chris Lattner24943d22010-06-08 16:52:24 +000042
43// Project includes
44#include "lldb/Host/Host.h"
Greg Clayton54e7afa2010-07-09 20:39:50 +000045#include "Utility/StringExtractorGDBRemote.h"
Chris Lattner24943d22010-06-08 16:52:24 +000046#include "GDBRemoteRegisterContext.h"
47#include "ProcessGDBRemote.h"
48#include "ProcessGDBRemoteLog.h"
49#include "ThreadGDBRemote.h"
Greg Clayton643ee732010-08-04 01:40:35 +000050#include "StopInfoMachException.h"
51
Chris Lattner24943d22010-06-08 16:52:24 +000052
Chris Lattner24943d22010-06-08 16:52:24 +000053
54#define DEBUGSERVER_BASENAME "debugserver"
55using namespace lldb;
56using namespace lldb_private;
57
Jim Inghamf9600482011-03-29 21:45:47 +000058static bool rand_initialized = false;
59
Chris Lattner24943d22010-06-08 16:52:24 +000060static inline uint16_t
61get_random_port ()
62{
Jim Inghamf9600482011-03-29 21:45:47 +000063 if (!rand_initialized)
64 {
Stephen Wilson60f19d52011-03-30 00:12:40 +000065 time_t seed = time(NULL);
66
Jim Inghamf9600482011-03-29 21:45:47 +000067 rand_initialized = true;
Stephen Wilson60f19d52011-03-30 00:12:40 +000068 srand(seed);
Jim Inghamf9600482011-03-29 21:45:47 +000069 }
Stephen Wilson50daf772011-03-25 18:16:28 +000070 return (rand() % (UINT16_MAX - 1000u)) + 1000u;
Chris Lattner24943d22010-06-08 16:52:24 +000071}
72
73
74const char *
75ProcessGDBRemote::GetPluginNameStatic()
76{
Greg Claytonb1888f22011-03-19 01:12:21 +000077 return "gdb-remote";
Chris Lattner24943d22010-06-08 16:52:24 +000078}
79
80const char *
81ProcessGDBRemote::GetPluginDescriptionStatic()
82{
83 return "GDB Remote protocol based debugging plug-in.";
84}
85
86void
87ProcessGDBRemote::Terminate()
88{
89 PluginManager::UnregisterPlugin (ProcessGDBRemote::CreateInstance);
90}
91
92
93Process*
94ProcessGDBRemote::CreateInstance (Target &target, Listener &listener)
95{
96 return new ProcessGDBRemote (target, listener);
97}
98
99bool
100ProcessGDBRemote::CanDebug(Target &target)
101{
102 // For now we are just making sure the file exists for a given module
103 ModuleSP exe_module_sp(target.GetExecutableModule());
104 if (exe_module_sp.get())
105 return exe_module_sp->GetFileSpec().Exists();
Jim Ingham7508e732010-08-09 23:31:02 +0000106 // However, if there is no executable module, we return true since we might be preparing to attach.
107 return true;
Chris Lattner24943d22010-06-08 16:52:24 +0000108}
109
110//----------------------------------------------------------------------
111// ProcessGDBRemote constructor
112//----------------------------------------------------------------------
113ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
114 Process (target, listener),
Chris Lattner24943d22010-06-08 16:52:24 +0000115 m_flags (0),
Chris Lattner24943d22010-06-08 16:52:24 +0000116 m_stdio_mutex (Mutex::eMutexTypeRecursive),
Greg Claytonb72d0f02011-04-12 05:54:46 +0000117 m_gdb_comm(false),
Chris Lattner24943d22010-06-08 16:52:24 +0000118 m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
Greg Clayton75ccf502010-08-21 02:22:51 +0000119 m_debugserver_thread (LLDB_INVALID_HOST_THREAD),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000120 m_last_stop_packet (),
Chris Lattner24943d22010-06-08 16:52:24 +0000121 m_register_info (),
Chris Lattner24943d22010-06-08 16:52:24 +0000122 m_async_broadcaster ("lldb.process.gdb-remote.async-broadcaster"),
123 m_async_thread (LLDB_INVALID_HOST_THREAD),
Greg Claytonc1f45872011-02-12 06:28:37 +0000124 m_continue_c_tids (),
125 m_continue_C_tids (),
126 m_continue_s_tids (),
127 m_continue_S_tids (),
Chris Lattner24943d22010-06-08 16:52:24 +0000128 m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS),
Greg Clayton54e7afa2010-07-09 20:39:50 +0000129 m_max_memory_size (512),
Jim Ingham7508e732010-08-09 23:31:02 +0000130 m_waiting_for_attach (false),
Jim Ingham55e01d82011-01-22 01:33:44 +0000131 m_local_debugserver (true),
132 m_thread_observation_bps()
Chris Lattner24943d22010-06-08 16:52:24 +0000133{
Greg Claytonff39f742011-04-01 00:29:43 +0000134 m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
135 m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
Chris Lattner24943d22010-06-08 16:52:24 +0000136}
137
138//----------------------------------------------------------------------
139// Destructor
140//----------------------------------------------------------------------
141ProcessGDBRemote::~ProcessGDBRemote()
142{
Greg Clayton09c81ef2011-02-08 01:34:25 +0000143 if (IS_VALID_LLDB_HOST_THREAD(m_debugserver_thread))
Greg Clayton75ccf502010-08-21 02:22:51 +0000144 {
145 Host::ThreadCancel (m_debugserver_thread, NULL);
146 thread_result_t thread_result;
147 Host::ThreadJoin (m_debugserver_thread, &thread_result, NULL);
148 m_debugserver_thread = LLDB_INVALID_HOST_THREAD;
149 }
Chris Lattner24943d22010-06-08 16:52:24 +0000150 // m_mach_process.UnregisterNotificationCallbacks (this);
151 Clear();
152}
153
154//----------------------------------------------------------------------
155// PluginInterface
156//----------------------------------------------------------------------
157const char *
158ProcessGDBRemote::GetPluginName()
159{
160 return "Process debugging plug-in that uses the GDB remote protocol";
161}
162
163const char *
164ProcessGDBRemote::GetShortPluginName()
165{
166 return GetPluginNameStatic();
167}
168
169uint32_t
170ProcessGDBRemote::GetPluginVersion()
171{
172 return 1;
173}
174
175void
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000176ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
Chris Lattner24943d22010-06-08 16:52:24 +0000177{
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000178 if (!force && m_register_info.GetNumRegisters() > 0)
179 return;
180
181 char packet[128];
Chris Lattner24943d22010-06-08 16:52:24 +0000182 m_register_info.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000183 uint32_t reg_offset = 0;
184 uint32_t reg_num = 0;
Greg Clayton61d043b2011-03-22 04:00:09 +0000185 StringExtractorGDBRemote::ResponseType response_type;
186 for (response_type = StringExtractorGDBRemote::eResponse;
187 response_type == StringExtractorGDBRemote::eResponse;
188 ++reg_num)
Chris Lattner24943d22010-06-08 16:52:24 +0000189 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000190 const int packet_len = ::snprintf (packet, sizeof(packet), "qRegisterInfo%x", reg_num);
191 assert (packet_len < sizeof(packet));
Chris Lattner24943d22010-06-08 16:52:24 +0000192 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000193 if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
Chris Lattner24943d22010-06-08 16:52:24 +0000194 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000195 response_type = response.GetResponseType();
196 if (response_type == StringExtractorGDBRemote::eResponse)
Chris Lattner24943d22010-06-08 16:52:24 +0000197 {
198 std::string name;
199 std::string value;
200 ConstString reg_name;
201 ConstString alt_name;
202 ConstString set_name;
203 RegisterInfo reg_info = { NULL, // Name
204 NULL, // Alt name
205 0, // byte size
206 reg_offset, // offset
207 eEncodingUint, // encoding
208 eFormatHex, // formate
Chris Lattner24943d22010-06-08 16:52:24 +0000209 {
210 LLDB_INVALID_REGNUM, // GCC reg num
211 LLDB_INVALID_REGNUM, // DWARF reg num
212 LLDB_INVALID_REGNUM, // generic reg num
Jason Molenda3a4ea242010-09-10 07:49:16 +0000213 reg_num, // GDB reg num
214 reg_num // native register number
Chris Lattner24943d22010-06-08 16:52:24 +0000215 }
216 };
217
218 while (response.GetNameColonValue(name, value))
219 {
220 if (name.compare("name") == 0)
221 {
222 reg_name.SetCString(value.c_str());
223 }
224 else if (name.compare("alt-name") == 0)
225 {
226 alt_name.SetCString(value.c_str());
227 }
228 else if (name.compare("bitsize") == 0)
229 {
230 reg_info.byte_size = Args::StringToUInt32(value.c_str(), 0, 0) / CHAR_BIT;
231 }
232 else if (name.compare("offset") == 0)
233 {
234 uint32_t offset = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0);
Jason Molenda53d96862010-06-11 23:44:18 +0000235 if (reg_offset != offset)
Chris Lattner24943d22010-06-08 16:52:24 +0000236 {
237 reg_offset = offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000238 }
239 }
240 else if (name.compare("encoding") == 0)
241 {
242 if (value.compare("uint") == 0)
243 reg_info.encoding = eEncodingUint;
244 else if (value.compare("sint") == 0)
245 reg_info.encoding = eEncodingSint;
246 else if (value.compare("ieee754") == 0)
247 reg_info.encoding = eEncodingIEEE754;
248 else if (value.compare("vector") == 0)
249 reg_info.encoding = eEncodingVector;
250 }
251 else if (name.compare("format") == 0)
252 {
253 if (value.compare("binary") == 0)
254 reg_info.format = eFormatBinary;
255 else if (value.compare("decimal") == 0)
256 reg_info.format = eFormatDecimal;
257 else if (value.compare("hex") == 0)
258 reg_info.format = eFormatHex;
259 else if (value.compare("float") == 0)
260 reg_info.format = eFormatFloat;
261 else if (value.compare("vector-sint8") == 0)
262 reg_info.format = eFormatVectorOfSInt8;
263 else if (value.compare("vector-uint8") == 0)
264 reg_info.format = eFormatVectorOfUInt8;
265 else if (value.compare("vector-sint16") == 0)
266 reg_info.format = eFormatVectorOfSInt16;
267 else if (value.compare("vector-uint16") == 0)
268 reg_info.format = eFormatVectorOfUInt16;
269 else if (value.compare("vector-sint32") == 0)
270 reg_info.format = eFormatVectorOfSInt32;
271 else if (value.compare("vector-uint32") == 0)
272 reg_info.format = eFormatVectorOfUInt32;
273 else if (value.compare("vector-float32") == 0)
274 reg_info.format = eFormatVectorOfFloat32;
275 else if (value.compare("vector-uint128") == 0)
276 reg_info.format = eFormatVectorOfUInt128;
277 }
278 else if (name.compare("set") == 0)
279 {
280 set_name.SetCString(value.c_str());
281 }
282 else if (name.compare("gcc") == 0)
283 {
284 reg_info.kinds[eRegisterKindGCC] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
285 }
286 else if (name.compare("dwarf") == 0)
287 {
288 reg_info.kinds[eRegisterKindDWARF] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
289 }
290 else if (name.compare("generic") == 0)
291 {
292 if (value.compare("pc") == 0)
293 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
294 else if (value.compare("sp") == 0)
295 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
296 else if (value.compare("fp") == 0)
297 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
298 else if (value.compare("ra") == 0)
299 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
300 else if (value.compare("flags") == 0)
301 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
302 }
303 }
304
Jason Molenda53d96862010-06-11 23:44:18 +0000305 reg_info.byte_offset = reg_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000306 assert (reg_info.byte_size != 0);
307 reg_offset += reg_info.byte_size;
308 m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
309 }
310 }
311 else
312 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000313 response_type = StringExtractorGDBRemote::eError;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000314 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000315 }
316 }
317
318 if (reg_num == 0)
319 {
320 // We didn't get anything. See if we are debugging ARM and fill with
321 // a hard coded register set until we can get an updated debugserver
322 // down on the devices.
Greg Clayton940b1032011-02-23 00:35:02 +0000323 if (GetTarget().GetArchitecture().GetMachine() == llvm::Triple::arm)
Chris Lattner24943d22010-06-08 16:52:24 +0000324 m_register_info.HardcodeARMRegisters();
325 }
326 m_register_info.Finalize ();
327}
328
329Error
330ProcessGDBRemote::WillLaunch (Module* module)
331{
332 return WillLaunchOrAttach ();
333}
334
335Error
Greg Clayton20d338f2010-11-18 05:57:03 +0000336ProcessGDBRemote::WillAttachToProcessWithID (lldb::pid_t pid)
Chris Lattner24943d22010-06-08 16:52:24 +0000337{
338 return WillLaunchOrAttach ();
339}
340
341Error
Greg Clayton20d338f2010-11-18 05:57:03 +0000342ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
Chris Lattner24943d22010-06-08 16:52:24 +0000343{
344 return WillLaunchOrAttach ();
345}
346
347Error
Greg Claytone71e2582011-02-04 01:58:07 +0000348ProcessGDBRemote::DoConnectRemote (const char *remote_url)
349{
350 Error error (WillLaunchOrAttach ());
351
352 if (error.Fail())
353 return error;
354
Greg Clayton180546b2011-04-30 01:09:13 +0000355 error = ConnectToDebugserver (remote_url);
Greg Claytone71e2582011-02-04 01:58:07 +0000356
357 if (error.Fail())
358 return error;
359 StartAsyncThread ();
360
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000361 lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
Greg Claytone71e2582011-02-04 01:58:07 +0000362 if (pid == LLDB_INVALID_PROCESS_ID)
363 {
364 // We don't have a valid process ID, so note that we are connected
365 // and could now request to launch or attach, or get remote process
366 // listings...
367 SetPrivateState (eStateConnected);
368 }
369 else
370 {
371 // We have a valid process
372 SetID (pid);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000373 UpdateThreadListIfNeeded ();
Greg Claytone71e2582011-02-04 01:58:07 +0000374 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000375 if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, response, false))
Greg Claytone71e2582011-02-04 01:58:07 +0000376 {
377 const StateType state = SetThreadStopInfo (response);
378 if (state == eStateStopped)
379 {
380 SetPrivateState (state);
381 }
382 else
383 error.SetErrorStringWithFormat ("Process %i was reported after connecting to '%s', but state was not stopped: %s", pid, remote_url, StateAsCString (state));
384 }
385 else
386 error.SetErrorStringWithFormat ("Process %i was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
387 }
388 return error;
389}
390
391Error
Chris Lattner24943d22010-06-08 16:52:24 +0000392ProcessGDBRemote::WillLaunchOrAttach ()
393{
394 Error error;
Chris Lattner24943d22010-06-08 16:52:24 +0000395 m_stdio_communication.Clear ();
Chris Lattner24943d22010-06-08 16:52:24 +0000396 return error;
397}
398
399//----------------------------------------------------------------------
400// Process Control
401//----------------------------------------------------------------------
402Error
403ProcessGDBRemote::DoLaunch
404(
405 Module* module,
406 char const *argv[],
407 char const *envp[],
Greg Clayton452bf612010-08-31 18:35:14 +0000408 uint32_t launch_flags,
Chris Lattner24943d22010-06-08 16:52:24 +0000409 const char *stdin_path,
410 const char *stdout_path,
Greg Claytonde915be2011-01-23 05:56:20 +0000411 const char *stderr_path,
412 const char *working_dir
Chris Lattner24943d22010-06-08 16:52:24 +0000413)
414{
Greg Clayton4b407112010-09-30 21:49:03 +0000415 Error error;
Chris Lattner24943d22010-06-08 16:52:24 +0000416 // ::LogSetBitMask (GDBR_LOG_DEFAULT);
417 // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
418 // ::LogSetLogFile ("/dev/stdout");
Chris Lattner24943d22010-06-08 16:52:24 +0000419
420 ObjectFile * object_file = module->GetObjectFile();
421 if (object_file)
422 {
Chris Lattner24943d22010-06-08 16:52:24 +0000423 char host_port[128];
424 snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
Greg Claytone71e2582011-02-04 01:58:07 +0000425 char connect_url[128];
426 snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
Chris Lattner24943d22010-06-08 16:52:24 +0000427
Greg Claytona2f74232011-02-24 22:24:29 +0000428 // Make sure we aren't already connected?
429 if (!m_gdb_comm.IsConnected())
Chris Lattner24943d22010-06-08 16:52:24 +0000430 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000431 error = StartDebugserverProcess (host_port);
Chris Lattner24943d22010-06-08 16:52:24 +0000432 if (error.Fail())
433 return error;
434
Greg Claytone71e2582011-02-04 01:58:07 +0000435 error = ConnectToDebugserver (connect_url);
Greg Claytona2f74232011-02-24 22:24:29 +0000436 }
437
438 if (error.Success())
439 {
440 lldb_utility::PseudoTerminal pty;
441 const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
Greg Claytonafb81862011-03-02 21:34:46 +0000442
443 // If the debugserver is local and we aren't disabling STDIO, lets use
444 // a pseudo terminal to instead of relying on the 'O' packets for stdio
445 // since 'O' packets can really slow down debugging if the inferior
446 // does a lot of output.
447 if (m_local_debugserver && !disable_stdio)
Greg Claytona2f74232011-02-24 22:24:29 +0000448 {
449 const char *slave_name = NULL;
450 if (stdin_path == NULL || stdout_path == NULL || stderr_path == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000451 {
Greg Claytona2f74232011-02-24 22:24:29 +0000452 if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
453 slave_name = pty.GetSlaveName (NULL, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000454 }
Greg Claytona2f74232011-02-24 22:24:29 +0000455 if (stdin_path == NULL)
456 stdin_path = slave_name;
Chris Lattner24943d22010-06-08 16:52:24 +0000457
Greg Claytona2f74232011-02-24 22:24:29 +0000458 if (stdout_path == NULL)
459 stdout_path = slave_name;
460
461 if (stderr_path == NULL)
462 stderr_path = slave_name;
463 }
464
Greg Claytonafb81862011-03-02 21:34:46 +0000465 // Set STDIN to /dev/null if we want STDIO disabled or if either
466 // STDOUT or STDERR have been set to something and STDIN hasn't
467 if (disable_stdio || (stdin_path == NULL && (stdout_path || stderr_path)))
Greg Claytona2f74232011-02-24 22:24:29 +0000468 stdin_path = "/dev/null";
469
Greg Claytonafb81862011-03-02 21:34:46 +0000470 // Set STDOUT to /dev/null if we want STDIO disabled or if either
471 // STDIN or STDERR have been set to something and STDOUT hasn't
472 if (disable_stdio || (stdout_path == NULL && (stdin_path || stderr_path)))
Greg Claytona2f74232011-02-24 22:24:29 +0000473 stdout_path = "/dev/null";
474
Greg Claytonafb81862011-03-02 21:34:46 +0000475 // Set STDERR to /dev/null if we want STDIO disabled or if either
476 // STDIN or STDOUT have been set to something and STDERR hasn't
477 if (disable_stdio || (stderr_path == NULL && (stdin_path || stdout_path)))
Greg Claytona2f74232011-02-24 22:24:29 +0000478 stderr_path = "/dev/null";
479
480 if (stdin_path)
481 m_gdb_comm.SetSTDIN (stdin_path);
482 if (stdout_path)
483 m_gdb_comm.SetSTDOUT (stdout_path);
484 if (stderr_path)
485 m_gdb_comm.SetSTDERR (stderr_path);
486
487 m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
488
Greg Claytona4582402011-05-08 04:53:50 +0000489 m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName());
Greg Claytona2f74232011-02-24 22:24:29 +0000490
491 if (working_dir && working_dir[0])
492 {
493 m_gdb_comm.SetWorkingDir (working_dir);
494 }
495
496 // Send the environment and the program + arguments after we connect
497 if (envp)
498 {
499 const char *env_entry;
500 for (int i=0; (env_entry = envp[i]); ++i)
Greg Clayton960d6a42010-08-03 00:35:52 +0000501 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000502 if (m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
Greg Claytona2f74232011-02-24 22:24:29 +0000503 break;
Greg Clayton960d6a42010-08-03 00:35:52 +0000504 }
Greg Claytona2f74232011-02-24 22:24:29 +0000505 }
Greg Clayton960d6a42010-08-03 00:35:52 +0000506
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000507 const uint32_t old_packet_timeout = m_gdb_comm.SetPacketTimeout (10);
508 int arg_packet_err = m_gdb_comm.SendArgumentsPacket (argv);
509 m_gdb_comm.SetPacketTimeout (old_packet_timeout);
Greg Claytona2f74232011-02-24 22:24:29 +0000510 if (arg_packet_err == 0)
511 {
512 std::string error_str;
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000513 if (m_gdb_comm.GetLaunchSuccess (error_str))
Chris Lattner24943d22010-06-08 16:52:24 +0000514 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000515 SetID (m_gdb_comm.GetCurrentProcessID ());
Chris Lattner24943d22010-06-08 16:52:24 +0000516 }
517 else
518 {
Greg Claytona2f74232011-02-24 22:24:29 +0000519 error.SetErrorString (error_str.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000520 }
Greg Claytona2f74232011-02-24 22:24:29 +0000521 }
522 else
523 {
524 error.SetErrorStringWithFormat("'A' packet returned an error: %i.\n", arg_packet_err);
525 }
Chris Lattner24943d22010-06-08 16:52:24 +0000526
Greg Claytona2f74232011-02-24 22:24:29 +0000527 if (GetID() == LLDB_INVALID_PROCESS_ID)
528 {
529 KillDebugserverProcess ();
530 return error;
531 }
532
533 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000534 if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, response, false))
Greg Claytona2f74232011-02-24 22:24:29 +0000535 {
536 SetPrivateState (SetThreadStopInfo (response));
537
538 if (!disable_stdio)
539 {
540 if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd)
541 SetUpProcessInputReader (pty.ReleaseMasterFileDescriptor());
542 }
Chris Lattner24943d22010-06-08 16:52:24 +0000543 }
544 }
Chris Lattner24943d22010-06-08 16:52:24 +0000545 }
546 else
547 {
548 // Set our user ID to an invalid process ID.
549 SetID(LLDB_INVALID_PROCESS_ID);
Greg Clayton940b1032011-02-23 00:35:02 +0000550 error.SetErrorStringWithFormat("Failed to get object file from '%s' for arch %s.\n",
551 module->GetFileSpec().GetFilename().AsCString(),
552 module->GetArchitecture().GetArchitectureName());
Chris Lattner24943d22010-06-08 16:52:24 +0000553 }
Chris Lattner24943d22010-06-08 16:52:24 +0000554 return error;
Greg Clayton4b407112010-09-30 21:49:03 +0000555
Chris Lattner24943d22010-06-08 16:52:24 +0000556}
557
558
559Error
Greg Claytone71e2582011-02-04 01:58:07 +0000560ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
Chris Lattner24943d22010-06-08 16:52:24 +0000561{
562 Error error;
563 // Sleep and wait a bit for debugserver to start to listen...
564 std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
565 if (conn_ap.get())
566 {
Chris Lattner24943d22010-06-08 16:52:24 +0000567 const uint32_t max_retry_count = 50;
568 uint32_t retry_count = 0;
569 while (!m_gdb_comm.IsConnected())
570 {
Greg Claytone71e2582011-02-04 01:58:07 +0000571 if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
Chris Lattner24943d22010-06-08 16:52:24 +0000572 {
573 m_gdb_comm.SetConnection (conn_ap.release());
574 break;
575 }
576 retry_count++;
577
578 if (retry_count >= max_retry_count)
579 break;
580
581 usleep (100000);
582 }
583 }
584
585 if (!m_gdb_comm.IsConnected())
586 {
587 if (error.Success())
588 error.SetErrorString("not connected to remote gdb server");
589 return error;
590 }
591
Greg Clayton24bc5d92011-03-30 18:16:51 +0000592 // We always seem to be able to open a connection to a local port
593 // so we need to make sure we can then send data to it. If we can't
594 // then we aren't actually connected to anything, so try and do the
595 // handshake with the remote GDB server and make sure that goes
596 // alright.
597 if (!m_gdb_comm.HandshakeWithServer (NULL))
Chris Lattner24943d22010-06-08 16:52:24 +0000598 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000599 m_gdb_comm.Disconnect();
600 if (error.Success())
601 error.SetErrorString("not connected to remote gdb server");
602 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000603 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000604 if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
605 m_debugserver_thread = Host::StartMonitoringChildProcess (MonitorDebugserverProcess,
606 this,
607 m_debugserver_pid,
608 false);
609 m_gdb_comm.ResetDiscoverableSettings();
610 m_gdb_comm.QueryNoAckModeSupported ();
611 m_gdb_comm.GetThreadSuffixSupported ();
612 m_gdb_comm.GetHostInfo ();
613 m_gdb_comm.GetVContSupported ('c');
Chris Lattner24943d22010-06-08 16:52:24 +0000614 return error;
615}
616
617void
618ProcessGDBRemote::DidLaunchOrAttach ()
619{
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000620 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
621 if (log)
622 log->Printf ("ProcessGDBRemote::DidLaunch()");
Greg Clayton75c703d2011-02-16 04:46:07 +0000623 if (GetID() != LLDB_INVALID_PROCESS_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000624 {
625 m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
626
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000627 BuildDynamicRegisterInfo (false);
Greg Clayton20d338f2010-11-18 05:57:03 +0000628
Chris Lattner24943d22010-06-08 16:52:24 +0000629 // See if the GDB server supports the qHostInfo information
Greg Claytonfc7920f2011-02-09 03:09:55 +0000630
Greg Claytoncb8977d2011-03-23 00:09:55 +0000631 const ArchSpec &gdb_remote_arch = m_gdb_comm.GetHostArchitecture();
632 if (gdb_remote_arch.IsValid())
Greg Claytonfc7920f2011-02-09 03:09:55 +0000633 {
Greg Claytoncb8977d2011-03-23 00:09:55 +0000634 ArchSpec &target_arch = GetTarget().GetArchitecture();
635
636 if (target_arch.IsValid())
637 {
638 // If the remote host is ARM and we have apple as the vendor, then
639 // ARM executables and shared libraries can have mixed ARM architectures.
640 // You can have an armv6 executable, and if the host is armv7, then the
641 // system will load the best possible architecture for all shared libraries
642 // it has, so we really need to take the remote host architecture as our
643 // defacto architecture in this case.
644
645 if (gdb_remote_arch.GetMachine() == llvm::Triple::arm &&
646 gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
647 {
648 target_arch = gdb_remote_arch;
649 }
650 else
651 {
652 // Fill in what is missing in the triple
653 const llvm::Triple &remote_triple = gdb_remote_arch.GetTriple();
654 llvm::Triple &target_triple = target_arch.GetTriple();
655 if (target_triple.getVendor() == llvm::Triple::UnknownVendor)
656 target_triple.setVendor (remote_triple.getVendor());
657
658 if (target_triple.getOS() == llvm::Triple::UnknownOS)
659 target_triple.setOS (remote_triple.getOS());
660
661 if (target_triple.getEnvironment() == llvm::Triple::UnknownEnvironment)
662 target_triple.setEnvironment (remote_triple.getEnvironment());
663 }
664 }
665 else
666 {
667 // The target doesn't have a valid architecture yet, set it from
668 // the architecture we got from the remote GDB server
669 target_arch = gdb_remote_arch;
670 }
Greg Claytonfc7920f2011-02-09 03:09:55 +0000671 }
Chris Lattner24943d22010-06-08 16:52:24 +0000672 }
673}
674
675void
676ProcessGDBRemote::DidLaunch ()
677{
678 DidLaunchOrAttach ();
Chris Lattner24943d22010-06-08 16:52:24 +0000679}
680
681Error
Greg Clayton54e7afa2010-07-09 20:39:50 +0000682ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
Chris Lattner24943d22010-06-08 16:52:24 +0000683{
684 Error error;
685 // Clear out and clean up from any current state
686 Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000687 if (attach_pid != LLDB_INVALID_PROCESS_ID)
688 {
Greg Claytona2f74232011-02-24 22:24:29 +0000689 // Make sure we aren't already connected?
690 if (!m_gdb_comm.IsConnected())
Chris Lattner24943d22010-06-08 16:52:24 +0000691 {
Greg Claytona2f74232011-02-24 22:24:29 +0000692 char host_port[128];
693 snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
694 char connect_url[128];
695 snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
Chris Lattner24943d22010-06-08 16:52:24 +0000696
Greg Claytonb72d0f02011-04-12 05:54:46 +0000697 error = StartDebugserverProcess (host_port);
Greg Claytona2f74232011-02-24 22:24:29 +0000698
699 if (error.Fail())
Chris Lattner24943d22010-06-08 16:52:24 +0000700 {
Greg Claytona2f74232011-02-24 22:24:29 +0000701 const char *error_string = error.AsCString();
702 if (error_string == NULL)
703 error_string = "unable to launch " DEBUGSERVER_BASENAME;
704
705 SetExitStatus (-1, error_string);
Chris Lattner24943d22010-06-08 16:52:24 +0000706 }
Greg Claytona2f74232011-02-24 22:24:29 +0000707 else
708 {
709 error = ConnectToDebugserver (connect_url);
710 }
711 }
712
713 if (error.Success())
714 {
715 char packet[64];
716 const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%x", attach_pid);
717
718 m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
Chris Lattner24943d22010-06-08 16:52:24 +0000719 }
720 }
Chris Lattner24943d22010-06-08 16:52:24 +0000721 return error;
722}
723
724size_t
725ProcessGDBRemote::AttachInputReaderCallback
726(
727 void *baton,
728 InputReader *reader,
729 lldb::InputReaderAction notification,
730 const char *bytes,
731 size_t bytes_len
732)
733{
734 if (notification == eInputReaderGotToken)
735 {
736 ProcessGDBRemote *gdb_process = (ProcessGDBRemote *)baton;
737 if (gdb_process->m_waiting_for_attach)
738 gdb_process->m_waiting_for_attach = false;
739 reader->SetIsDone(true);
740 return 1;
741 }
742 return 0;
743}
744
745Error
Greg Clayton54e7afa2010-07-09 20:39:50 +0000746ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait_for_launch)
Chris Lattner24943d22010-06-08 16:52:24 +0000747{
748 Error error;
749 // Clear out and clean up from any current state
750 Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000751
Chris Lattner24943d22010-06-08 16:52:24 +0000752 if (process_name && process_name[0])
753 {
Greg Claytona2f74232011-02-24 22:24:29 +0000754 // Make sure we aren't already connected?
755 if (!m_gdb_comm.IsConnected())
Chris Lattner24943d22010-06-08 16:52:24 +0000756 {
Greg Claytona2f74232011-02-24 22:24:29 +0000757 char host_port[128];
758 snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
759 char connect_url[128];
760 snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
761
Greg Claytonb72d0f02011-04-12 05:54:46 +0000762 error = StartDebugserverProcess (host_port);
Greg Claytona2f74232011-02-24 22:24:29 +0000763 if (error.Fail())
Chris Lattner24943d22010-06-08 16:52:24 +0000764 {
Greg Claytona2f74232011-02-24 22:24:29 +0000765 const char *error_string = error.AsCString();
766 if (error_string == NULL)
767 error_string = "unable to launch " DEBUGSERVER_BASENAME;
Chris Lattner24943d22010-06-08 16:52:24 +0000768
Greg Claytona2f74232011-02-24 22:24:29 +0000769 SetExitStatus (-1, error_string);
Chris Lattner24943d22010-06-08 16:52:24 +0000770 }
Greg Claytona2f74232011-02-24 22:24:29 +0000771 else
772 {
773 error = ConnectToDebugserver (connect_url);
774 }
775 }
776
777 if (error.Success())
778 {
779 StreamString packet;
780
781 if (wait_for_launch)
782 packet.PutCString("vAttachWait");
783 else
784 packet.PutCString("vAttachName");
785 packet.PutChar(';');
786 packet.PutBytesAsRawHex8(process_name, strlen(process_name), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
787
788 m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));
789
Chris Lattner24943d22010-06-08 16:52:24 +0000790 }
791 }
Chris Lattner24943d22010-06-08 16:52:24 +0000792 return error;
793}
794
Chris Lattner24943d22010-06-08 16:52:24 +0000795
796void
797ProcessGDBRemote::DidAttach ()
798{
Greg Claytone71e2582011-02-04 01:58:07 +0000799 DidLaunchOrAttach ();
Chris Lattner24943d22010-06-08 16:52:24 +0000800}
801
802Error
803ProcessGDBRemote::WillResume ()
804{
Greg Claytonc1f45872011-02-12 06:28:37 +0000805 m_continue_c_tids.clear();
806 m_continue_C_tids.clear();
807 m_continue_s_tids.clear();
808 m_continue_S_tids.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000809 return Error();
810}
811
812Error
813ProcessGDBRemote::DoResume ()
814{
Jim Ingham3ae449a2010-11-17 02:32:00 +0000815 Error error;
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000816 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
817 if (log)
818 log->Printf ("ProcessGDBRemote::Resume()");
Greg Claytonb749a262010-12-03 06:02:24 +0000819
820 Listener listener ("gdb-remote.resume-packet-sent");
821 if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
822 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000823 StreamString continue_packet;
824 bool continue_packet_error = false;
825 if (m_gdb_comm.HasAnyVContSupport ())
826 {
827 continue_packet.PutCString ("vCont");
828
829 if (!m_continue_c_tids.empty())
830 {
831 if (m_gdb_comm.GetVContSupported ('c'))
832 {
833 for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos)
834 continue_packet.Printf(";c:%4.4x", *t_pos);
835 }
836 else
837 continue_packet_error = true;
838 }
839
840 if (!continue_packet_error && !m_continue_C_tids.empty())
841 {
842 if (m_gdb_comm.GetVContSupported ('C'))
843 {
844 for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos)
845 continue_packet.Printf(";C%2.2x:%4.4x", s_pos->second, s_pos->first);
846 }
847 else
848 continue_packet_error = true;
849 }
Greg Claytonb749a262010-12-03 06:02:24 +0000850
Greg Claytonc1f45872011-02-12 06:28:37 +0000851 if (!continue_packet_error && !m_continue_s_tids.empty())
852 {
853 if (m_gdb_comm.GetVContSupported ('s'))
854 {
855 for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos)
856 continue_packet.Printf(";s:%4.4x", *t_pos);
857 }
858 else
859 continue_packet_error = true;
860 }
861
862 if (!continue_packet_error && !m_continue_S_tids.empty())
863 {
864 if (m_gdb_comm.GetVContSupported ('S'))
865 {
866 for (tid_sig_collection::const_iterator s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); s_pos != s_end; ++s_pos)
867 continue_packet.Printf(";S%2.2x:%4.4x", s_pos->second, s_pos->first);
868 }
869 else
870 continue_packet_error = true;
871 }
872
873 if (continue_packet_error)
874 continue_packet.GetString().clear();
875 }
876 else
877 continue_packet_error = true;
878
879 if (continue_packet_error)
880 {
881 continue_packet_error = false;
882 // Either no vCont support, or we tried to use part of the vCont
883 // packet that wasn't supported by the remote GDB server.
884 // We need to try and make a simple packet that can do our continue
885 const size_t num_threads = GetThreadList().GetSize();
886 const size_t num_continue_c_tids = m_continue_c_tids.size();
887 const size_t num_continue_C_tids = m_continue_C_tids.size();
888 const size_t num_continue_s_tids = m_continue_s_tids.size();
889 const size_t num_continue_S_tids = m_continue_S_tids.size();
890 if (num_continue_c_tids > 0)
891 {
892 if (num_continue_c_tids == num_threads)
893 {
894 // All threads are resuming...
Greg Claytonb72d0f02011-04-12 05:54:46 +0000895 m_gdb_comm.SetCurrentThreadForRun (-1);
Greg Claytonc1f45872011-02-12 06:28:37 +0000896 continue_packet.PutChar ('c');
897 }
898 else if (num_continue_c_tids == 1 &&
899 num_continue_C_tids == 0 &&
900 num_continue_s_tids == 0 &&
901 num_continue_S_tids == 0 )
902 {
903 // Only one thread is continuing
Greg Claytonb72d0f02011-04-12 05:54:46 +0000904 m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
Greg Claytonc1f45872011-02-12 06:28:37 +0000905 continue_packet.PutChar ('c');
906 }
907 else
908 {
909 // We can't represent this continue packet....
910 continue_packet_error = true;
911 }
912 }
913
914 if (!continue_packet_error && num_continue_C_tids > 0)
915 {
916 if (num_continue_C_tids == num_threads)
917 {
918 const int continue_signo = m_continue_C_tids.front().second;
919 if (num_continue_C_tids > 1)
920 {
921 for (size_t i=1; i<num_threads; ++i)
922 {
923 if (m_continue_C_tids[i].second != continue_signo)
924 continue_packet_error = true;
925 }
926 }
927 if (!continue_packet_error)
928 {
929 // Add threads continuing with the same signo...
Greg Claytonb72d0f02011-04-12 05:54:46 +0000930 m_gdb_comm.SetCurrentThreadForRun (-1);
Greg Claytonc1f45872011-02-12 06:28:37 +0000931 continue_packet.Printf("C%2.2x", continue_signo);
932 }
933 }
934 else if (num_continue_c_tids == 0 &&
935 num_continue_C_tids == 1 &&
936 num_continue_s_tids == 0 &&
937 num_continue_S_tids == 0 )
938 {
939 // Only one thread is continuing with signal
Greg Claytonb72d0f02011-04-12 05:54:46 +0000940 m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first);
Greg Claytonc1f45872011-02-12 06:28:37 +0000941 continue_packet.Printf("C%2.2x", m_continue_C_tids.front().second);
942 }
943 else
944 {
945 // We can't represent this continue packet....
946 continue_packet_error = true;
947 }
948 }
949
950 if (!continue_packet_error && num_continue_s_tids > 0)
951 {
952 if (num_continue_s_tids == num_threads)
953 {
954 // All threads are resuming...
Greg Claytonb72d0f02011-04-12 05:54:46 +0000955 m_gdb_comm.SetCurrentThreadForRun (-1);
Greg Claytonc1f45872011-02-12 06:28:37 +0000956 continue_packet.PutChar ('s');
957 }
958 else if (num_continue_c_tids == 0 &&
959 num_continue_C_tids == 0 &&
960 num_continue_s_tids == 1 &&
961 num_continue_S_tids == 0 )
962 {
963 // Only one thread is stepping
Greg Claytonb72d0f02011-04-12 05:54:46 +0000964 m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
Greg Claytonc1f45872011-02-12 06:28:37 +0000965 continue_packet.PutChar ('s');
966 }
967 else
968 {
969 // We can't represent this continue packet....
970 continue_packet_error = true;
971 }
972 }
973
974 if (!continue_packet_error && num_continue_S_tids > 0)
975 {
976 if (num_continue_S_tids == num_threads)
977 {
978 const int step_signo = m_continue_S_tids.front().second;
979 // Are all threads trying to step with the same signal?
980 if (num_continue_S_tids > 1)
981 {
982 for (size_t i=1; i<num_threads; ++i)
983 {
984 if (m_continue_S_tids[i].second != step_signo)
985 continue_packet_error = true;
986 }
987 }
988 if (!continue_packet_error)
989 {
990 // Add threads stepping with the same signo...
Greg Claytonb72d0f02011-04-12 05:54:46 +0000991 m_gdb_comm.SetCurrentThreadForRun (-1);
Greg Claytonc1f45872011-02-12 06:28:37 +0000992 continue_packet.Printf("S%2.2x", step_signo);
993 }
994 }
995 else if (num_continue_c_tids == 0 &&
996 num_continue_C_tids == 0 &&
997 num_continue_s_tids == 0 &&
998 num_continue_S_tids == 1 )
999 {
1000 // Only one thread is stepping with signal
Greg Claytonb72d0f02011-04-12 05:54:46 +00001001 m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first);
Greg Claytonc1f45872011-02-12 06:28:37 +00001002 continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
1003 }
1004 else
1005 {
1006 // We can't represent this continue packet....
1007 continue_packet_error = true;
1008 }
1009 }
1010 }
1011
1012 if (continue_packet_error)
1013 {
1014 error.SetErrorString ("can't make continue packet for this resume");
1015 }
1016 else
1017 {
1018 EventSP event_sp;
1019 TimeValue timeout;
1020 timeout = TimeValue::Now();
1021 timeout.OffsetWithSeconds (5);
1022 m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
1023
1024 if (listener.WaitForEvent (&timeout, event_sp) == false)
1025 error.SetErrorString("Resume timed out.");
1026 }
Greg Claytonb749a262010-12-03 06:02:24 +00001027 }
1028
Jim Ingham3ae449a2010-11-17 02:32:00 +00001029 return error;
Chris Lattner24943d22010-06-08 16:52:24 +00001030}
1031
Chris Lattner24943d22010-06-08 16:52:24 +00001032uint32_t
1033ProcessGDBRemote::UpdateThreadListIfNeeded ()
1034{
1035 // locker will keep a mutex locked until it goes out of scope
Greg Claytone005f2c2010-11-06 01:53:30 +00001036 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
Greg Claytonf3d0b0c2010-10-27 03:32:59 +00001037 if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
Chris Lattner24943d22010-06-08 16:52:24 +00001038 log->Printf ("ProcessGDBRemote::%s (pid = %i)", __FUNCTION__, GetID());
1039
Greg Clayton5205f0b2010-09-03 17:10:42 +00001040 Mutex::Locker locker (m_thread_list.GetMutex ());
Chris Lattner24943d22010-06-08 16:52:24 +00001041 const uint32_t stop_id = GetStopID();
1042 if (m_thread_list.GetSize(false) == 0 || stop_id != m_thread_list.GetStopID())
1043 {
1044 // Update the thread list's stop id immediately so we don't recurse into this function.
1045 ThreadList curr_thread_list (this);
1046 curr_thread_list.SetStopID(stop_id);
1047
1048 Error err;
1049 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001050 for (m_gdb_comm.SendPacketAndWaitForResponse("qfThreadInfo", response, false);
Greg Clayton61d043b2011-03-22 04:00:09 +00001051 response.IsNormalResponse();
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001052 m_gdb_comm.SendPacketAndWaitForResponse("qsThreadInfo", response, false))
Chris Lattner24943d22010-06-08 16:52:24 +00001053 {
1054 char ch = response.GetChar();
1055 if (ch == 'l')
1056 break;
1057 if (ch == 'm')
1058 {
1059 do
1060 {
1061 tid_t tid = response.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
1062
1063 if (tid != LLDB_INVALID_THREAD_ID)
1064 {
1065 ThreadSP thread_sp (GetThreadList().FindThreadByID (tid, false));
Greg Claytona875b642011-01-09 21:07:35 +00001066 if (!thread_sp)
Chris Lattner24943d22010-06-08 16:52:24 +00001067 thread_sp.reset (new ThreadGDBRemote (*this, tid));
1068 curr_thread_list.AddThread(thread_sp);
1069 }
1070
1071 ch = response.GetChar();
1072 } while (ch == ',');
1073 }
1074 }
1075
1076 m_thread_list = curr_thread_list;
1077
1078 SetThreadStopInfo (m_last_stop_packet);
1079 }
1080 return GetThreadList().GetSize(false);
1081}
1082
1083
1084StateType
1085ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
1086{
1087 const char stop_type = stop_packet.GetChar();
1088 switch (stop_type)
1089 {
1090 case 'T':
1091 case 'S':
1092 {
Greg Claytonc3c46612011-02-15 00:19:15 +00001093 if (GetStopID() == 0)
1094 {
1095 // Our first stop, make sure we have a process ID, and also make
1096 // sure we know about our registers
1097 if (GetID() == LLDB_INVALID_PROCESS_ID)
1098 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001099 lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
Greg Claytonc3c46612011-02-15 00:19:15 +00001100 if (pid != LLDB_INVALID_PROCESS_ID)
1101 SetID (pid);
1102 }
1103 BuildDynamicRegisterInfo (true);
1104 }
Chris Lattner24943d22010-06-08 16:52:24 +00001105 // Stop with signal and thread info
1106 const uint8_t signo = stop_packet.GetHexU8();
1107 std::string name;
1108 std::string value;
1109 std::string thread_name;
1110 uint32_t exc_type = 0;
Greg Clayton7661a982010-07-23 16:45:51 +00001111 std::vector<addr_t> exc_data;
Chris Lattner24943d22010-06-08 16:52:24 +00001112 uint32_t tid = LLDB_INVALID_THREAD_ID;
1113 addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
1114 uint32_t exc_data_count = 0;
Greg Claytona875b642011-01-09 21:07:35 +00001115 ThreadSP thread_sp;
1116
Chris Lattner24943d22010-06-08 16:52:24 +00001117 while (stop_packet.GetNameColonValue(name, value))
1118 {
1119 if (name.compare("metype") == 0)
1120 {
1121 // exception type in big endian hex
1122 exc_type = Args::StringToUInt32 (value.c_str(), 0, 16);
1123 }
1124 else if (name.compare("mecount") == 0)
1125 {
1126 // exception count in big endian hex
1127 exc_data_count = Args::StringToUInt32 (value.c_str(), 0, 16);
1128 }
1129 else if (name.compare("medata") == 0)
1130 {
1131 // exception data in big endian hex
1132 exc_data.push_back(Args::StringToUInt64 (value.c_str(), 0, 16));
1133 }
1134 else if (name.compare("thread") == 0)
1135 {
1136 // thread in big endian hex
1137 tid = Args::StringToUInt32 (value.c_str(), 0, 16);
Greg Claytonc3c46612011-02-15 00:19:15 +00001138 Mutex::Locker locker (m_thread_list.GetMutex ());
Greg Claytona875b642011-01-09 21:07:35 +00001139 thread_sp = m_thread_list.FindThreadByID(tid, false);
Greg Claytonc3c46612011-02-15 00:19:15 +00001140 if (!thread_sp)
1141 {
1142 // Create the thread if we need to
1143 thread_sp.reset (new ThreadGDBRemote (*this, tid));
1144 m_thread_list.AddThread(thread_sp);
1145 }
Chris Lattner24943d22010-06-08 16:52:24 +00001146 }
Greg Clayton4862fa22011-01-08 03:17:57 +00001147 else if (name.compare("hexname") == 0)
1148 {
1149 StringExtractor name_extractor;
1150 // Swap "value" over into "name_extractor"
1151 name_extractor.GetStringRef().swap(value);
1152 // Now convert the HEX bytes into a string value
1153 name_extractor.GetHexByteString (value);
1154 thread_name.swap (value);
1155 }
Chris Lattner24943d22010-06-08 16:52:24 +00001156 else if (name.compare("name") == 0)
1157 {
1158 thread_name.swap (value);
1159 }
Greg Clayton0a7f75f2010-09-09 06:32:46 +00001160 else if (name.compare("qaddr") == 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001161 {
1162 thread_dispatch_qaddr = Args::StringToUInt64 (value.c_str(), 0, 16);
1163 }
Greg Claytona875b642011-01-09 21:07:35 +00001164 else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1]))
1165 {
1166 // We have a register number that contains an expedited
1167 // register value. Lets supply this register to our thread
1168 // so it won't have to go and read it.
1169 if (thread_sp)
1170 {
1171 uint32_t reg = Args::StringToUInt32 (name.c_str(), UINT32_MAX, 16);
1172
1173 if (reg != UINT32_MAX)
1174 {
1175 StringExtractor reg_value_extractor;
1176 // Swap "value" over into "reg_value_extractor"
1177 reg_value_extractor.GetStringRef().swap(value);
Greg Claytonc3c46612011-02-15 00:19:15 +00001178 if (!static_cast<ThreadGDBRemote *> (thread_sp.get())->PrivateSetRegisterValue (reg, reg_value_extractor))
1179 {
1180 Host::SetCrashDescriptionWithFormat("Setting thread register '%s' (decoded to %u (0x%x)) with value '%s' for stop packet: '%s'",
1181 name.c_str(),
1182 reg,
1183 reg,
1184 reg_value_extractor.GetStringRef().c_str(),
1185 stop_packet.GetStringRef().c_str());
1186 }
Greg Claytona875b642011-01-09 21:07:35 +00001187 }
1188 }
1189 }
Chris Lattner24943d22010-06-08 16:52:24 +00001190 }
Chris Lattner24943d22010-06-08 16:52:24 +00001191
1192 if (thread_sp)
1193 {
1194 ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
1195
1196 gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
Jim Ingham9082c8a2011-01-28 02:23:12 +00001197 gdb_thread->SetName (thread_name.empty() ? NULL : thread_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001198 if (exc_type != 0)
1199 {
Greg Claytonbdcb6ab2011-01-25 23:55:37 +00001200 const size_t exc_data_size = exc_data.size();
Greg Clayton643ee732010-08-04 01:40:35 +00001201
1202 gdb_thread->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
1203 exc_type,
Greg Claytonbdcb6ab2011-01-25 23:55:37 +00001204 exc_data_size,
1205 exc_data_size >= 1 ? exc_data[0] : 0,
1206 exc_data_size >= 2 ? exc_data[1] : 0));
Chris Lattner24943d22010-06-08 16:52:24 +00001207 }
1208 else if (signo)
1209 {
Greg Clayton643ee732010-08-04 01:40:35 +00001210 gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo));
Chris Lattner24943d22010-06-08 16:52:24 +00001211 }
1212 else
1213 {
Greg Clayton643ee732010-08-04 01:40:35 +00001214 StopInfoSP invalid_stop_info_sp;
1215 gdb_thread->SetStopInfo (invalid_stop_info_sp);
Chris Lattner24943d22010-06-08 16:52:24 +00001216 }
1217 }
1218 return eStateStopped;
1219 }
1220 break;
1221
1222 case 'W':
1223 // process exited
1224 return eStateExited;
1225
1226 default:
1227 break;
1228 }
1229 return eStateInvalid;
1230}
1231
1232void
1233ProcessGDBRemote::RefreshStateAfterStop ()
1234{
Jim Ingham7508e732010-08-09 23:31:02 +00001235 // FIXME - add a variable to tell that we're in the middle of attaching if we
1236 // need to know that.
Chris Lattner24943d22010-06-08 16:52:24 +00001237 // We must be attaching if we don't already have a valid architecture
Jim Ingham7508e732010-08-09 23:31:02 +00001238// if (!GetTarget().GetArchitecture().IsValid())
1239// {
1240// Module *exe_module = GetTarget().GetExecutableModule().get();
1241// if (exe_module)
1242// m_arch_spec = exe_module->GetArchitecture();
1243// }
1244
Chris Lattner24943d22010-06-08 16:52:24 +00001245 // Let all threads recover from stopping and do any clean up based
1246 // on the previous thread state (if any).
1247 m_thread_list.RefreshStateAfterStop();
1248
1249 // Discover new threads:
1250 UpdateThreadListIfNeeded ();
1251}
1252
1253Error
Jim Ingham3ae449a2010-11-17 02:32:00 +00001254ProcessGDBRemote::DoHalt (bool &caused_stop)
Chris Lattner24943d22010-06-08 16:52:24 +00001255{
1256 Error error;
Jim Ingham3ae449a2010-11-17 02:32:00 +00001257
Greg Claytona4881d02011-01-22 07:12:45 +00001258 bool timed_out = false;
1259 Mutex::Locker locker;
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001260
1261 if (m_public_state.GetValue() == eStateAttaching)
Greg Clayton20d338f2010-11-18 05:57:03 +00001262 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001263 // We are being asked to halt during an attach. We need to just close
1264 // our file handle and debugserver will go away, and we can be done...
1265 m_gdb_comm.Disconnect();
Greg Clayton20d338f2010-11-18 05:57:03 +00001266 }
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001267 else
1268 {
1269 if (!m_gdb_comm.SendInterrupt (locker, 2, caused_stop, timed_out))
1270 {
1271 if (timed_out)
1272 error.SetErrorString("timed out sending interrupt packet");
1273 else
1274 error.SetErrorString("unknown error sending interrupt packet");
1275 }
1276 }
Chris Lattner24943d22010-06-08 16:52:24 +00001277 return error;
1278}
1279
1280Error
Greg Clayton72e1c782011-01-22 23:43:18 +00001281ProcessGDBRemote::InterruptIfRunning
1282(
1283 bool discard_thread_plans,
1284 bool catch_stop_event,
Greg Clayton72e1c782011-01-22 23:43:18 +00001285 EventSP &stop_event_sp
1286)
Chris Lattner24943d22010-06-08 16:52:24 +00001287{
1288 Error error;
Chris Lattner24943d22010-06-08 16:52:24 +00001289
Greg Clayton2860ba92011-01-23 19:58:49 +00001290 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
1291
Greg Clayton68ca8232011-01-25 02:58:48 +00001292 bool paused_private_state_thread = false;
Greg Clayton2860ba92011-01-23 19:58:49 +00001293 const bool is_running = m_gdb_comm.IsRunning();
1294 if (log)
Greg Clayton68ca8232011-01-25 02:58:48 +00001295 log->Printf ("ProcessGDBRemote::InterruptIfRunning(discard_thread_plans=%i, catch_stop_event=%i) is_running=%i",
Greg Clayton2860ba92011-01-23 19:58:49 +00001296 discard_thread_plans,
Greg Clayton68ca8232011-01-25 02:58:48 +00001297 catch_stop_event,
Greg Clayton2860ba92011-01-23 19:58:49 +00001298 is_running);
1299
Greg Clayton2860ba92011-01-23 19:58:49 +00001300 if (discard_thread_plans)
1301 {
1302 if (log)
1303 log->Printf ("ProcessGDBRemote::InterruptIfRunning() discarding all thread plans");
1304 m_thread_list.DiscardThreadPlans();
1305 }
1306 if (is_running)
Greg Clayton4fb400f2010-09-27 21:07:38 +00001307 {
Greg Clayton68ca8232011-01-25 02:58:48 +00001308 if (catch_stop_event)
1309 {
1310 if (log)
1311 log->Printf ("ProcessGDBRemote::InterruptIfRunning() pausing private state thread");
1312 PausePrivateStateThread();
1313 paused_private_state_thread = true;
1314 }
1315
Greg Clayton4fb400f2010-09-27 21:07:38 +00001316 bool timed_out = false;
Greg Claytona4881d02011-01-22 07:12:45 +00001317 bool sent_interrupt = false;
Greg Clayton4fb400f2010-09-27 21:07:38 +00001318 Mutex::Locker locker;
Greg Clayton72e1c782011-01-22 23:43:18 +00001319
Greg Clayton72e1c782011-01-22 23:43:18 +00001320 if (!m_gdb_comm.SendInterrupt (locker, 1, sent_interrupt, timed_out))
Greg Clayton4fb400f2010-09-27 21:07:38 +00001321 {
1322 if (timed_out)
1323 error.SetErrorString("timed out sending interrupt packet");
1324 else
1325 error.SetErrorString("unknown error sending interrupt packet");
Greg Clayton68ca8232011-01-25 02:58:48 +00001326 if (paused_private_state_thread)
Greg Clayton72e1c782011-01-22 23:43:18 +00001327 ResumePrivateStateThread();
1328 return error;
Greg Clayton4fb400f2010-09-27 21:07:38 +00001329 }
Greg Clayton72e1c782011-01-22 23:43:18 +00001330
Greg Clayton72e1c782011-01-22 23:43:18 +00001331 if (catch_stop_event)
1332 {
Greg Clayton68ca8232011-01-25 02:58:48 +00001333 // LISTEN HERE
Greg Clayton72e1c782011-01-22 23:43:18 +00001334 TimeValue timeout_time;
1335 timeout_time = TimeValue::Now();
Greg Clayton68ca8232011-01-25 02:58:48 +00001336 timeout_time.OffsetWithSeconds(5);
1337 StateType state = WaitForStateChangedEventsPrivate (&timeout_time, stop_event_sp);
Greg Clayton2860ba92011-01-23 19:58:49 +00001338
Greg Claytonbdcb6ab2011-01-25 23:55:37 +00001339 timed_out = state == eStateInvalid;
Greg Clayton2860ba92011-01-23 19:58:49 +00001340 if (log)
1341 log->Printf ("ProcessGDBRemote::InterruptIfRunning() catch stop event: state = %s, timed-out=%i", StateAsCString(state), timed_out);
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001342
Greg Clayton2860ba92011-01-23 19:58:49 +00001343 if (timed_out)
Greg Clayton72e1c782011-01-22 23:43:18 +00001344 error.SetErrorString("unable to verify target stopped");
1345 }
1346
Greg Clayton68ca8232011-01-25 02:58:48 +00001347 if (paused_private_state_thread)
Greg Clayton2860ba92011-01-23 19:58:49 +00001348 {
1349 if (log)
1350 log->Printf ("ProcessGDBRemote::InterruptIfRunning() resuming private state thread");
Greg Clayton72e1c782011-01-22 23:43:18 +00001351 ResumePrivateStateThread();
Greg Clayton2860ba92011-01-23 19:58:49 +00001352 }
Greg Clayton4fb400f2010-09-27 21:07:38 +00001353 }
Chris Lattner24943d22010-06-08 16:52:24 +00001354 return error;
1355}
1356
Greg Clayton4fb400f2010-09-27 21:07:38 +00001357Error
Greg Clayton72e1c782011-01-22 23:43:18 +00001358ProcessGDBRemote::WillDetach ()
1359{
Greg Clayton2860ba92011-01-23 19:58:49 +00001360 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
1361 if (log)
1362 log->Printf ("ProcessGDBRemote::WillDetach()");
1363
Greg Clayton72e1c782011-01-22 23:43:18 +00001364 bool discard_thread_plans = true;
1365 bool catch_stop_event = true;
Greg Clayton72e1c782011-01-22 23:43:18 +00001366 EventSP event_sp;
Greg Clayton68ca8232011-01-25 02:58:48 +00001367 return InterruptIfRunning (discard_thread_plans, catch_stop_event, event_sp);
Greg Clayton72e1c782011-01-22 23:43:18 +00001368}
1369
1370Error
Greg Clayton4fb400f2010-09-27 21:07:38 +00001371ProcessGDBRemote::DoDetach()
1372{
1373 Error error;
Greg Claytone005f2c2010-11-06 01:53:30 +00001374 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Greg Clayton4fb400f2010-09-27 21:07:38 +00001375 if (log)
1376 log->Printf ("ProcessGDBRemote::DoDetach()");
1377
1378 DisableAllBreakpointSites ();
1379
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001380 m_thread_list.DiscardThreadPlans();
Greg Clayton4fb400f2010-09-27 21:07:38 +00001381
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001382 size_t response_size = m_gdb_comm.SendPacket ("D", 1);
1383 if (log)
Greg Clayton4fb400f2010-09-27 21:07:38 +00001384 {
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001385 if (response_size)
1386 log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
1387 else
1388 log->PutCString ("ProcessGDBRemote::DoDetach() detach packet send failed");
Greg Clayton4fb400f2010-09-27 21:07:38 +00001389 }
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001390 // Sleep for one second to let the process get all detached...
Greg Clayton4fb400f2010-09-27 21:07:38 +00001391 StopAsyncThread ();
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001392
Greg Clayton4fb400f2010-09-27 21:07:38 +00001393 m_gdb_comm.StopReadThread();
Greg Clayton4fb400f2010-09-27 21:07:38 +00001394 m_gdb_comm.Disconnect(); // Disconnect from the debug server.
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001395
1396 SetPrivateState (eStateDetached);
1397 ResumePrivateStateThread();
1398
1399 //KillDebugserverProcess ();
Greg Clayton4fb400f2010-09-27 21:07:38 +00001400 return error;
1401}
Chris Lattner24943d22010-06-08 16:52:24 +00001402
1403Error
1404ProcessGDBRemote::DoDestroy ()
1405{
1406 Error error;
Greg Claytone005f2c2010-11-06 01:53:30 +00001407 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00001408 if (log)
1409 log->Printf ("ProcessGDBRemote::DoDestroy()");
1410
1411 // Interrupt if our inferior is running...
Greg Claytona4881d02011-01-22 07:12:45 +00001412 if (m_gdb_comm.IsConnected())
Chris Lattner24943d22010-06-08 16:52:24 +00001413 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001414 if (m_public_state.GetValue() == eStateAttaching)
Greg Clayton27a8dd72011-01-25 04:57:42 +00001415 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001416 // We are being asked to halt during an attach. We need to just close
1417 // our file handle and debugserver will go away, and we can be done...
1418 m_gdb_comm.Disconnect();
Greg Clayton27a8dd72011-01-25 04:57:42 +00001419 }
1420 else
Greg Clayton72e1c782011-01-22 23:43:18 +00001421 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001422
1423 StringExtractorGDBRemote response;
1424 bool send_async = true;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001425 if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async))
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001426 {
1427 char packet_cmd = response.GetChar(0);
1428
1429 if (packet_cmd == 'W' || packet_cmd == 'X')
1430 {
1431 m_last_stop_packet = response;
1432 SetExitStatus(response.GetHexU8(), NULL);
1433 }
1434 }
1435 else
1436 {
1437 SetExitStatus(SIGABRT, NULL);
1438 //error.SetErrorString("kill packet failed");
1439 }
Greg Clayton72e1c782011-01-22 23:43:18 +00001440 }
1441 }
Chris Lattner24943d22010-06-08 16:52:24 +00001442 StopAsyncThread ();
1443 m_gdb_comm.StopReadThread();
1444 KillDebugserverProcess ();
Johnny Chenc5b15db2010-09-03 22:35:47 +00001445 m_gdb_comm.Disconnect(); // Disconnect from the debug server.
Chris Lattner24943d22010-06-08 16:52:24 +00001446 return error;
1447}
1448
Chris Lattner24943d22010-06-08 16:52:24 +00001449//------------------------------------------------------------------
1450// Process Queries
1451//------------------------------------------------------------------
1452
1453bool
1454ProcessGDBRemote::IsAlive ()
1455{
Greg Clayton58e844b2010-12-08 05:08:21 +00001456 return m_gdb_comm.IsConnected() && m_private_state.GetValue() != eStateExited;
Chris Lattner24943d22010-06-08 16:52:24 +00001457}
1458
1459addr_t
1460ProcessGDBRemote::GetImageInfoAddress()
1461{
1462 if (!m_gdb_comm.IsRunning())
1463 {
1464 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001465 if (m_gdb_comm.SendPacketAndWaitForResponse("qShlibInfoAddr", ::strlen ("qShlibInfoAddr"), response, false))
Chris Lattner24943d22010-06-08 16:52:24 +00001466 {
Greg Clayton61d043b2011-03-22 04:00:09 +00001467 if (response.IsNormalResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001468 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
1469 }
1470 }
1471 return LLDB_INVALID_ADDRESS;
1472}
1473
Chris Lattner24943d22010-06-08 16:52:24 +00001474//------------------------------------------------------------------
1475// Process Memory
1476//------------------------------------------------------------------
1477size_t
1478ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
1479{
1480 if (size > m_max_memory_size)
1481 {
1482 // Keep memory read sizes down to a sane limit. This function will be
1483 // called multiple times in order to complete the task by
1484 // lldb_private::Process so it is ok to do this.
1485 size = m_max_memory_size;
1486 }
1487
1488 char packet[64];
1489 const int packet_len = ::snprintf (packet, sizeof(packet), "m%llx,%zx", (uint64_t)addr, size);
1490 assert (packet_len + 1 < sizeof(packet));
1491 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001492 if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
Chris Lattner24943d22010-06-08 16:52:24 +00001493 {
Greg Clayton61d043b2011-03-22 04:00:09 +00001494 if (response.IsNormalResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001495 {
1496 error.Clear();
1497 return response.GetHexBytes(buf, size, '\xdd');
1498 }
Greg Clayton61d043b2011-03-22 04:00:09 +00001499 else if (response.IsErrorResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001500 error.SetErrorStringWithFormat("gdb remote returned an error: %s", response.GetStringRef().c_str());
Greg Clayton61d043b2011-03-22 04:00:09 +00001501 else if (response.IsUnsupportedResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001502 error.SetErrorStringWithFormat("'%s' packet unsupported", packet);
1503 else
1504 error.SetErrorStringWithFormat("unexpected response to '%s': '%s'", packet, response.GetStringRef().c_str());
1505 }
1506 else
1507 {
1508 error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet);
1509 }
1510 return 0;
1511}
1512
1513size_t
1514ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
1515{
1516 StreamString packet;
1517 packet.Printf("M%llx,%zx:", addr, size);
Greg Claytoncd548032011-02-01 01:31:41 +00001518 packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +00001519 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001520 if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true))
Chris Lattner24943d22010-06-08 16:52:24 +00001521 {
Greg Clayton61d043b2011-03-22 04:00:09 +00001522 if (response.IsOKResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001523 {
1524 error.Clear();
1525 return size;
1526 }
Greg Clayton61d043b2011-03-22 04:00:09 +00001527 else if (response.IsErrorResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001528 error.SetErrorStringWithFormat("gdb remote returned an error: %s", response.GetStringRef().c_str());
Greg Clayton61d043b2011-03-22 04:00:09 +00001529 else if (response.IsUnsupportedResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001530 error.SetErrorStringWithFormat("'%s' packet unsupported", packet.GetString().c_str());
1531 else
1532 error.SetErrorStringWithFormat("unexpected response to '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str());
1533 }
1534 else
1535 {
1536 error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet.GetString().c_str());
1537 }
1538 return 0;
1539}
1540
1541lldb::addr_t
1542ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
1543{
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001544 addr_t allocated_addr = m_gdb_comm.AllocateMemory (size, permissions);
Chris Lattner24943d22010-06-08 16:52:24 +00001545 if (allocated_addr == LLDB_INVALID_ADDRESS)
1546 error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %u", size, permissions);
1547 else
1548 error.Clear();
1549 return allocated_addr;
1550}
1551
1552Error
1553ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
1554{
1555 Error error;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001556 if (!m_gdb_comm.DeallocateMemory (addr))
Chris Lattner24943d22010-06-08 16:52:24 +00001557 error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
1558 return error;
1559}
1560
1561
1562//------------------------------------------------------------------
1563// Process STDIO
1564//------------------------------------------------------------------
1565
1566size_t
1567ProcessGDBRemote::GetSTDOUT (char *buf, size_t buf_size, Error &error)
1568{
1569 Mutex::Locker locker(m_stdio_mutex);
1570 size_t bytes_available = m_stdout_data.size();
1571 if (bytes_available > 0)
1572 {
Greg Clayton0bfda0b2011-02-05 02:25:06 +00001573 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
1574 if (log)
1575 log->Printf ("ProcessGDBRemote::%s (&%p[%u]) ...", __FUNCTION__, buf, buf_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001576 if (bytes_available > buf_size)
1577 {
Greg Clayton53d68e72010-07-20 22:52:08 +00001578 memcpy(buf, m_stdout_data.c_str(), buf_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001579 m_stdout_data.erase(0, buf_size);
1580 bytes_available = buf_size;
1581 }
1582 else
1583 {
Greg Clayton53d68e72010-07-20 22:52:08 +00001584 memcpy(buf, m_stdout_data.c_str(), bytes_available);
Chris Lattner24943d22010-06-08 16:52:24 +00001585 m_stdout_data.clear();
1586
1587 //ResetEventBits(eBroadcastBitSTDOUT);
1588 }
1589 }
1590 return bytes_available;
1591}
1592
1593size_t
1594ProcessGDBRemote::GetSTDERR (char *buf, size_t buf_size, Error &error)
1595{
1596 // Can we get STDERR through the remote protocol?
1597 return 0;
1598}
1599
1600size_t
1601ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error)
1602{
1603 if (m_stdio_communication.IsConnected())
1604 {
1605 ConnectionStatus status;
1606 m_stdio_communication.Write(src, src_len, status, NULL);
1607 }
1608 return 0;
1609}
1610
1611Error
1612ProcessGDBRemote::EnableBreakpoint (BreakpointSite *bp_site)
1613{
1614 Error error;
1615 assert (bp_site != NULL);
1616
Greg Claytone005f2c2010-11-06 01:53:30 +00001617 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +00001618 user_id_t site_id = bp_site->GetID();
1619 const addr_t addr = bp_site->GetLoadAddress();
1620 if (log)
1621 log->Printf ("ProcessGDBRemote::EnableBreakpoint (size_id = %d) address = 0x%llx", site_id, (uint64_t)addr);
1622
1623 if (bp_site->IsEnabled())
1624 {
1625 if (log)
1626 log->Printf ("ProcessGDBRemote::EnableBreakpoint (size_id = %d) address = 0x%llx -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
1627 return error;
1628 }
1629 else
1630 {
1631 const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
1632
1633 if (bp_site->HardwarePreferred())
1634 {
1635 // Try and set hardware breakpoint, and if that fails, fall through
1636 // and set a software breakpoint?
Greg Claytonb72d0f02011-04-12 05:54:46 +00001637 if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointHardware))
Chris Lattner24943d22010-06-08 16:52:24 +00001638 {
Greg Claytonb72d0f02011-04-12 05:54:46 +00001639 if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001640 {
1641 bp_site->SetEnabled(true);
Greg Claytonb72d0f02011-04-12 05:54:46 +00001642 bp_site->SetType (BreakpointSite::eHardware);
Chris Lattner24943d22010-06-08 16:52:24 +00001643 return error;
1644 }
Chris Lattner24943d22010-06-08 16:52:24 +00001645 }
1646 }
Greg Claytonb72d0f02011-04-12 05:54:46 +00001647
1648 if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
Chris Lattner24943d22010-06-08 16:52:24 +00001649 {
Greg Claytonb72d0f02011-04-12 05:54:46 +00001650 if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
1651 {
1652 bp_site->SetEnabled(true);
1653 bp_site->SetType (BreakpointSite::eExternal);
1654 return error;
1655 }
Chris Lattner24943d22010-06-08 16:52:24 +00001656 }
Greg Claytonb72d0f02011-04-12 05:54:46 +00001657
1658 return EnableSoftwareBreakpoint (bp_site);
Chris Lattner24943d22010-06-08 16:52:24 +00001659 }
1660
1661 if (log)
1662 {
1663 const char *err_string = error.AsCString();
1664 log->Printf ("ProcessGDBRemote::EnableBreakpoint() error for breakpoint at 0x%8.8llx: %s",
1665 bp_site->GetLoadAddress(),
1666 err_string ? err_string : "NULL");
1667 }
1668 // We shouldn't reach here on a successful breakpoint enable...
1669 if (error.Success())
1670 error.SetErrorToGenericError();
1671 return error;
1672}
1673
1674Error
1675ProcessGDBRemote::DisableBreakpoint (BreakpointSite *bp_site)
1676{
1677 Error error;
1678 assert (bp_site != NULL);
1679 addr_t addr = bp_site->GetLoadAddress();
1680 user_id_t site_id = bp_site->GetID();
Greg Claytone005f2c2010-11-06 01:53:30 +00001681 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +00001682 if (log)
1683 log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx", site_id, (uint64_t)addr);
1684
1685 if (bp_site->IsEnabled())
1686 {
1687 const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
1688
Greg Claytonb72d0f02011-04-12 05:54:46 +00001689 BreakpointSite::Type bp_type = bp_site->GetType();
1690 switch (bp_type)
Chris Lattner24943d22010-06-08 16:52:24 +00001691 {
Greg Claytonb72d0f02011-04-12 05:54:46 +00001692 case BreakpointSite::eSoftware:
1693 error = DisableSoftwareBreakpoint (bp_site);
1694 break;
1695
1696 case BreakpointSite::eHardware:
1697 if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
1698 error.SetErrorToGenericError();
1699 break;
1700
1701 case BreakpointSite::eExternal:
1702 if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
1703 error.SetErrorToGenericError();
1704 break;
Chris Lattner24943d22010-06-08 16:52:24 +00001705 }
Greg Claytonb72d0f02011-04-12 05:54:46 +00001706 if (error.Success())
1707 bp_site->SetEnabled(false);
Chris Lattner24943d22010-06-08 16:52:24 +00001708 }
1709 else
1710 {
1711 if (log)
1712 log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS (already disabled)", site_id, (uint64_t)addr);
1713 return error;
1714 }
1715
1716 if (error.Success())
1717 error.SetErrorToGenericError();
1718 return error;
1719}
1720
1721Error
1722ProcessGDBRemote::EnableWatchpoint (WatchpointLocation *wp)
1723{
1724 Error error;
1725 if (wp)
1726 {
1727 user_id_t watchID = wp->GetID();
1728 addr_t addr = wp->GetLoadAddress();
Greg Claytone005f2c2010-11-06 01:53:30 +00001729 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +00001730 if (log)
1731 log->Printf ("ProcessGDBRemote::EnableWatchpoint(watchID = %d)", watchID);
1732 if (wp->IsEnabled())
1733 {
1734 if (log)
1735 log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %d) addr = 0x%8.8llx: watchpoint already enabled.", watchID, (uint64_t)addr);
1736 return error;
1737 }
1738 else
1739 {
1740 // Pass down an appropriate z/Z packet...
1741 error.SetErrorString("watchpoints not supported");
1742 }
1743 }
1744 else
1745 {
1746 error.SetErrorString("Watchpoint location argument was NULL.");
1747 }
1748 if (error.Success())
1749 error.SetErrorToGenericError();
1750 return error;
1751}
1752
1753Error
1754ProcessGDBRemote::DisableWatchpoint (WatchpointLocation *wp)
1755{
1756 Error error;
1757 if (wp)
1758 {
1759 user_id_t watchID = wp->GetID();
1760
Greg Claytone005f2c2010-11-06 01:53:30 +00001761 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +00001762
1763 addr_t addr = wp->GetLoadAddress();
1764 if (log)
1765 log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %d) addr = 0x%8.8llx", watchID, (uint64_t)addr);
1766
1767 if (wp->IsHardware())
1768 {
1769 // Pass down an appropriate z/Z packet...
1770 error.SetErrorString("watchpoints not supported");
1771 }
1772 // TODO: clear software watchpoints if we implement them
1773 }
1774 else
1775 {
1776 error.SetErrorString("Watchpoint location argument was NULL.");
1777 }
1778 if (error.Success())
1779 error.SetErrorToGenericError();
1780 return error;
1781}
1782
1783void
1784ProcessGDBRemote::Clear()
1785{
1786 m_flags = 0;
1787 m_thread_list.Clear();
1788 {
1789 Mutex::Locker locker(m_stdio_mutex);
1790 m_stdout_data.clear();
1791 }
Chris Lattner24943d22010-06-08 16:52:24 +00001792}
1793
1794Error
1795ProcessGDBRemote::DoSignal (int signo)
1796{
1797 Error error;
Greg Claytone005f2c2010-11-06 01:53:30 +00001798 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00001799 if (log)
1800 log->Printf ("ProcessGDBRemote::DoSignal (signal = %d)", signo);
1801
1802 if (!m_gdb_comm.SendAsyncSignal (signo))
1803 error.SetErrorStringWithFormat("failed to send signal %i", signo);
1804 return error;
1805}
1806
Chris Lattner24943d22010-06-08 16:52:24 +00001807Error
Greg Claytonb72d0f02011-04-12 05:54:46 +00001808ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url) // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
Chris Lattner24943d22010-06-08 16:52:24 +00001809{
1810 Error error;
1811 if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
1812 {
1813 // If we locate debugserver, keep that located version around
1814 static FileSpec g_debugserver_file_spec;
1815
Greg Claytonb72d0f02011-04-12 05:54:46 +00001816 ProcessLaunchInfo launch_info;
Chris Lattner24943d22010-06-08 16:52:24 +00001817 char debugserver_path[PATH_MAX];
Greg Claytonb72d0f02011-04-12 05:54:46 +00001818 FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
Chris Lattner24943d22010-06-08 16:52:24 +00001819
1820 // Always check to see if we have an environment override for the path
1821 // to the debugserver to use and use it if we do.
1822 const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
1823 if (env_debugserver_path)
Greg Clayton537a7a82010-10-20 20:54:39 +00001824 debugserver_file_spec.SetFile (env_debugserver_path, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001825 else
1826 debugserver_file_spec = g_debugserver_file_spec;
1827 bool debugserver_exists = debugserver_file_spec.Exists();
1828 if (!debugserver_exists)
1829 {
1830 // The debugserver binary is in the LLDB.framework/Resources
1831 // directory.
Greg Clayton24b48ff2010-10-17 22:03:32 +00001832 if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
Chris Lattner24943d22010-06-08 16:52:24 +00001833 {
Greg Clayton24b48ff2010-10-17 22:03:32 +00001834 debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
Chris Lattner24943d22010-06-08 16:52:24 +00001835 debugserver_exists = debugserver_file_spec.Exists();
Greg Clayton24b48ff2010-10-17 22:03:32 +00001836 if (debugserver_exists)
1837 {
1838 g_debugserver_file_spec = debugserver_file_spec;
1839 }
1840 else
1841 {
1842 g_debugserver_file_spec.Clear();
1843 debugserver_file_spec.Clear();
1844 }
Chris Lattner24943d22010-06-08 16:52:24 +00001845 }
1846 }
1847
1848 if (debugserver_exists)
1849 {
1850 debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
1851
1852 m_stdio_communication.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001853
Greg Claytone005f2c2010-11-06 01:53:30 +00001854 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00001855
Greg Claytonb72d0f02011-04-12 05:54:46 +00001856 Args &debugserver_args = launch_info.GetArguments();
Chris Lattner24943d22010-06-08 16:52:24 +00001857 char arg_cstr[PATH_MAX];
Chris Lattner24943d22010-06-08 16:52:24 +00001858
Chris Lattner24943d22010-06-08 16:52:24 +00001859 // Start args with "debugserver /file/path -r --"
1860 debugserver_args.AppendArgument(debugserver_path);
1861 debugserver_args.AppendArgument(debugserver_url);
Greg Clayton24b48ff2010-10-17 22:03:32 +00001862 // use native registers, not the GDB registers
1863 debugserver_args.AppendArgument("--native-regs");
1864 // make debugserver run in its own session so signals generated by
1865 // special terminal key sequences (^C) don't affect debugserver
1866 debugserver_args.AppendArgument("--setsid");
Chris Lattner24943d22010-06-08 16:52:24 +00001867
Chris Lattner24943d22010-06-08 16:52:24 +00001868 const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
1869 if (env_debugserver_log_file)
1870 {
1871 ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
1872 debugserver_args.AppendArgument(arg_cstr);
1873 }
1874
1875 const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
1876 if (env_debugserver_log_flags)
1877 {
1878 ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
1879 debugserver_args.AppendArgument(arg_cstr);
1880 }
Greg Claytoncc3e6402011-01-25 06:55:13 +00001881// debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001882// debugserver_args.AppendArgument("--log-flags=0x802e0e");
Chris Lattner24943d22010-06-08 16:52:24 +00001883
Greg Claytonb72d0f02011-04-12 05:54:46 +00001884 // We currently send down all arguments, attach pids, or attach
1885 // process names in dedicated GDB server packets, so we don't need
1886 // to pass them as arguments. This is currently because of all the
1887 // things we need to setup prior to launching: the environment,
1888 // current working dir, file actions, etc.
1889#if 0
Chris Lattner24943d22010-06-08 16:52:24 +00001890 // Now append the program arguments
Greg Claytona2f74232011-02-24 22:24:29 +00001891 if (inferior_argv)
Chris Lattner24943d22010-06-08 16:52:24 +00001892 {
Greg Claytona2f74232011-02-24 22:24:29 +00001893 // Terminate the debugserver args so we can now append the inferior args
1894 debugserver_args.AppendArgument("--");
Chris Lattner24943d22010-06-08 16:52:24 +00001895
Greg Claytona2f74232011-02-24 22:24:29 +00001896 for (int i = 0; inferior_argv[i] != NULL; ++i)
1897 debugserver_args.AppendArgument (inferior_argv[i]);
Chris Lattner24943d22010-06-08 16:52:24 +00001898 }
1899 else if (attach_pid != LLDB_INVALID_PROCESS_ID)
1900 {
1901 ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
1902 debugserver_args.AppendArgument (arg_cstr);
1903 }
1904 else if (attach_name && attach_name[0])
1905 {
1906 if (wait_for_launch)
1907 debugserver_args.AppendArgument ("--waitfor");
1908 else
1909 debugserver_args.AppendArgument ("--attach");
1910 debugserver_args.AppendArgument (attach_name);
1911 }
Chris Lattner24943d22010-06-08 16:52:24 +00001912#endif
Greg Claytonb72d0f02011-04-12 05:54:46 +00001913
1914 ProcessLaunchInfo::FileAction file_action;
1915
1916 // Close STDIN, STDOUT and STDERR. We might need to redirect them
1917 // to "/dev/null" if we run into any problems.
1918 file_action.Close (STDIN_FILENO);
1919 launch_info.AppendFileAction (file_action);
1920 file_action.Close (STDOUT_FILENO);
1921 launch_info.AppendFileAction (file_action);
1922 file_action.Close (STDERR_FILENO);
1923 launch_info.AppendFileAction (file_action);
Chris Lattner24943d22010-06-08 16:52:24 +00001924
1925 if (log)
1926 {
1927 StreamString strm;
1928 debugserver_args.Dump (&strm);
1929 log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData());
1930 }
1931
Greg Claytonb72d0f02011-04-12 05:54:46 +00001932 error = Host::LaunchProcess(launch_info);
Greg Claytone9d0df42010-07-02 01:29:13 +00001933
Greg Claytonb72d0f02011-04-12 05:54:46 +00001934 if (error.Success ())
1935 m_debugserver_pid = launch_info.GetProcessID();
1936 else
Chris Lattner24943d22010-06-08 16:52:24 +00001937 m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
1938
1939 if (error.Fail() || log)
Greg Claytonb72d0f02011-04-12 05:54:46 +00001940 error.PutToLog(log.get(), "Host::LaunchProcess (launch_info) => pid=%i, path='%s'", m_debugserver_pid, debugserver_path);
Chris Lattner24943d22010-06-08 16:52:24 +00001941 }
1942 else
1943 {
1944 error.SetErrorStringWithFormat ("Unable to locate " DEBUGSERVER_BASENAME ".\n");
1945 }
1946
1947 if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
1948 StartAsyncThread ();
1949 }
1950 return error;
1951}
1952
1953bool
1954ProcessGDBRemote::MonitorDebugserverProcess
1955(
1956 void *callback_baton,
1957 lldb::pid_t debugserver_pid,
1958 int signo, // Zero for no signal
1959 int exit_status // Exit value of process if signal is zero
1960)
1961{
1962 // We pass in the ProcessGDBRemote inferior process it and name it
1963 // "gdb_remote_pid". The process ID is passed in the "callback_baton"
1964 // pointer value itself, thus we need the double cast...
1965
1966 // "debugserver_pid" argument passed in is the process ID for
1967 // debugserver that we are tracking...
1968
Greg Clayton75ccf502010-08-21 02:22:51 +00001969 ProcessGDBRemote *process = (ProcessGDBRemote *)callback_baton;
Greg Clayton72e1c782011-01-22 23:43:18 +00001970
1971 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
1972 if (log)
1973 log->Printf ("ProcessGDBRemote::MonitorDebugserverProcess (baton=%p, pid=%i, signo=%i (0x%x), exit_status=%i)", callback_baton, debugserver_pid, signo, signo, exit_status);
1974
Greg Clayton75ccf502010-08-21 02:22:51 +00001975 if (process)
Chris Lattner24943d22010-06-08 16:52:24 +00001976 {
Greg Clayton75ccf502010-08-21 02:22:51 +00001977 // Sleep for a half a second to make sure our inferior process has
1978 // time to set its exit status before we set it incorrectly when
1979 // both the debugserver and the inferior process shut down.
1980 usleep (500000);
1981 // If our process hasn't yet exited, debugserver might have died.
1982 // If the process did exit, the we are reaping it.
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001983 const StateType state = process->GetState();
1984
1985 if (process->m_debugserver_pid != LLDB_INVALID_PROCESS_ID &&
1986 state != eStateInvalid &&
1987 state != eStateUnloaded &&
1988 state != eStateExited &&
1989 state != eStateDetached)
Chris Lattner24943d22010-06-08 16:52:24 +00001990 {
Greg Clayton75ccf502010-08-21 02:22:51 +00001991 char error_str[1024];
1992 if (signo)
Chris Lattner24943d22010-06-08 16:52:24 +00001993 {
Greg Clayton75ccf502010-08-21 02:22:51 +00001994 const char *signal_cstr = process->GetUnixSignals().GetSignalAsCString (signo);
1995 if (signal_cstr)
1996 ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
Chris Lattner24943d22010-06-08 16:52:24 +00001997 else
Greg Clayton75ccf502010-08-21 02:22:51 +00001998 ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %i", signo);
Chris Lattner24943d22010-06-08 16:52:24 +00001999 }
2000 else
2001 {
Greg Clayton75ccf502010-08-21 02:22:51 +00002002 ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", exit_status);
Chris Lattner24943d22010-06-08 16:52:24 +00002003 }
Greg Clayton75ccf502010-08-21 02:22:51 +00002004
2005 process->SetExitStatus (-1, error_str);
2006 }
Greg Clayton3b2c41c2010-10-18 04:14:23 +00002007 // Debugserver has exited we need to let our ProcessGDBRemote
2008 // know that it no longer has a debugserver instance
2009 process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
2010 // We are returning true to this function below, so we can
2011 // forget about the monitor handle.
2012 process->m_debugserver_thread = LLDB_INVALID_HOST_THREAD;
Chris Lattner24943d22010-06-08 16:52:24 +00002013 }
2014 return true;
2015}
2016
2017void
2018ProcessGDBRemote::KillDebugserverProcess ()
2019{
2020 if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
2021 {
2022 ::kill (m_debugserver_pid, SIGINT);
2023 m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
2024 }
2025}
2026
2027void
2028ProcessGDBRemote::Initialize()
2029{
2030 static bool g_initialized = false;
2031
2032 if (g_initialized == false)
2033 {
2034 g_initialized = true;
2035 PluginManager::RegisterPlugin (GetPluginNameStatic(),
2036 GetPluginDescriptionStatic(),
2037 CreateInstance);
2038
2039 Log::Callbacks log_callbacks = {
2040 ProcessGDBRemoteLog::DisableLog,
2041 ProcessGDBRemoteLog::EnableLog,
2042 ProcessGDBRemoteLog::ListLogCategories
2043 };
2044
2045 Log::RegisterLogChannel (ProcessGDBRemote::GetPluginNameStatic(), log_callbacks);
2046 }
2047}
2048
2049bool
Chris Lattner24943d22010-06-08 16:52:24 +00002050ProcessGDBRemote::StartAsyncThread ()
2051{
Greg Claytone005f2c2010-11-06 01:53:30 +00002052 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00002053
2054 if (log)
2055 log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
2056
2057 // Create a thread that watches our internal state and controls which
2058 // events make it to clients (into the DCProcess event queue).
2059 m_async_thread = Host::ThreadCreate ("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
Greg Clayton09c81ef2011-02-08 01:34:25 +00002060 return IS_VALID_LLDB_HOST_THREAD(m_async_thread);
Chris Lattner24943d22010-06-08 16:52:24 +00002061}
2062
2063void
2064ProcessGDBRemote::StopAsyncThread ()
2065{
Greg Claytone005f2c2010-11-06 01:53:30 +00002066 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00002067
2068 if (log)
2069 log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
2070
2071 m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
2072
2073 // Stop the stdio thread
Greg Clayton09c81ef2011-02-08 01:34:25 +00002074 if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
Chris Lattner24943d22010-06-08 16:52:24 +00002075 {
2076 Host::ThreadJoin (m_async_thread, NULL, NULL);
2077 }
2078}
2079
2080
2081void *
2082ProcessGDBRemote::AsyncThread (void *arg)
2083{
2084 ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
2085
Greg Claytone005f2c2010-11-06 01:53:30 +00002086 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00002087 if (log)
2088 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
2089
2090 Listener listener ("ProcessGDBRemote::AsyncThread");
2091 EventSP event_sp;
2092 const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
2093 eBroadcastBitAsyncThreadShouldExit;
2094
2095 if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
2096 {
Greg Claytona2f74232011-02-24 22:24:29 +00002097 listener.StartListeningForEvents (&process->m_gdb_comm, Communication::eBroadcastBitReadThreadDidExit);
2098
Chris Lattner24943d22010-06-08 16:52:24 +00002099 bool done = false;
2100 while (!done)
2101 {
2102 if (log)
2103 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
2104 if (listener.WaitForEvent (NULL, event_sp))
2105 {
2106 const uint32_t event_type = event_sp->GetType();
Greg Claytona2f74232011-02-24 22:24:29 +00002107 if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
Chris Lattner24943d22010-06-08 16:52:24 +00002108 {
Greg Claytona2f74232011-02-24 22:24:29 +00002109 if (log)
2110 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
Chris Lattner24943d22010-06-08 16:52:24 +00002111
Greg Claytona2f74232011-02-24 22:24:29 +00002112 switch (event_type)
2113 {
2114 case eBroadcastBitAsyncContinue:
Chris Lattner24943d22010-06-08 16:52:24 +00002115 {
Greg Claytona2f74232011-02-24 22:24:29 +00002116 const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
Chris Lattner24943d22010-06-08 16:52:24 +00002117
Greg Claytona2f74232011-02-24 22:24:29 +00002118 if (continue_packet)
Chris Lattner24943d22010-06-08 16:52:24 +00002119 {
Greg Claytona2f74232011-02-24 22:24:29 +00002120 const char *continue_cstr = (const char *)continue_packet->GetBytes ();
2121 const size_t continue_cstr_len = continue_packet->GetByteSize ();
2122 if (log)
2123 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
Chris Lattner24943d22010-06-08 16:52:24 +00002124
Greg Claytona2f74232011-02-24 22:24:29 +00002125 if (::strstr (continue_cstr, "vAttach") == NULL)
2126 process->SetPrivateState(eStateRunning);
2127 StringExtractorGDBRemote response;
2128 StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
Chris Lattner24943d22010-06-08 16:52:24 +00002129
Greg Claytona2f74232011-02-24 22:24:29 +00002130 switch (stop_state)
2131 {
2132 case eStateStopped:
2133 case eStateCrashed:
2134 case eStateSuspended:
2135 process->m_last_stop_packet = response;
2136 process->m_last_stop_packet.SetFilePos (0);
2137 process->SetPrivateState (stop_state);
2138 break;
Chris Lattner24943d22010-06-08 16:52:24 +00002139
Greg Claytona2f74232011-02-24 22:24:29 +00002140 case eStateExited:
2141 process->m_last_stop_packet = response;
2142 process->m_last_stop_packet.SetFilePos (0);
2143 response.SetFilePos(1);
2144 process->SetExitStatus(response.GetHexU8(), NULL);
2145 done = true;
2146 break;
2147
2148 case eStateInvalid:
2149 process->SetExitStatus(-1, "lost connection");
2150 break;
2151
2152 default:
2153 process->SetPrivateState (stop_state);
2154 break;
2155 }
Chris Lattner24943d22010-06-08 16:52:24 +00002156 }
2157 }
Greg Claytona2f74232011-02-24 22:24:29 +00002158 break;
Chris Lattner24943d22010-06-08 16:52:24 +00002159
Greg Claytona2f74232011-02-24 22:24:29 +00002160 case eBroadcastBitAsyncThreadShouldExit:
2161 if (log)
2162 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
2163 done = true;
2164 break;
Chris Lattner24943d22010-06-08 16:52:24 +00002165
Greg Claytona2f74232011-02-24 22:24:29 +00002166 default:
2167 if (log)
2168 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
2169 done = true;
2170 break;
2171 }
2172 }
2173 else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
2174 {
2175 if (event_type & Communication::eBroadcastBitReadThreadDidExit)
2176 {
2177 process->SetExitStatus (-1, "lost connection");
Chris Lattner24943d22010-06-08 16:52:24 +00002178 done = true;
Greg Claytona2f74232011-02-24 22:24:29 +00002179 }
Chris Lattner24943d22010-06-08 16:52:24 +00002180 }
2181 }
2182 else
2183 {
2184 if (log)
2185 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
2186 done = true;
2187 }
2188 }
2189 }
2190
2191 if (log)
2192 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
2193
2194 process->m_async_thread = LLDB_INVALID_HOST_THREAD;
2195 return NULL;
2196}
2197
Chris Lattner24943d22010-06-08 16:52:24 +00002198const char *
2199ProcessGDBRemote::GetDispatchQueueNameForThread
2200(
2201 addr_t thread_dispatch_qaddr,
2202 std::string &dispatch_queue_name
2203)
2204{
2205 dispatch_queue_name.clear();
2206 if (thread_dispatch_qaddr != 0 && thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
2207 {
2208 // Cache the dispatch_queue_offsets_addr value so we don't always have
2209 // to look it up
2210 if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
2211 {
Greg Claytonaf6e9e42010-10-12 17:33:06 +00002212 static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
2213 const Symbol *dispatch_queue_offsets_symbol = NULL;
Greg Clayton24bc5d92011-03-30 18:16:51 +00002214 ModuleSP module_sp(GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib", false), NULL, NULL));
Greg Claytonaf6e9e42010-10-12 17:33:06 +00002215 if (module_sp)
2216 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
2217
2218 if (dispatch_queue_offsets_symbol == NULL)
2219 {
Greg Clayton24bc5d92011-03-30 18:16:51 +00002220 module_sp = GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libdispatch.dylib", false), NULL, NULL);
Greg Claytonaf6e9e42010-10-12 17:33:06 +00002221 if (module_sp)
2222 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
2223 }
Chris Lattner24943d22010-06-08 16:52:24 +00002224 if (dispatch_queue_offsets_symbol)
Greg Claytoneea26402010-09-14 23:36:40 +00002225 m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetValue().GetLoadAddress(&m_target);
Chris Lattner24943d22010-06-08 16:52:24 +00002226
2227 if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
2228 return NULL;
2229 }
2230
2231 uint8_t memory_buffer[8];
Greg Clayton395fc332011-02-15 21:59:32 +00002232 DataExtractor data (memory_buffer,
2233 sizeof(memory_buffer),
2234 m_target.GetArchitecture().GetByteOrder(),
2235 m_target.GetArchitecture().GetAddressByteSize());
Chris Lattner24943d22010-06-08 16:52:24 +00002236
2237 // Excerpt from src/queue_private.h
2238 struct dispatch_queue_offsets_s
2239 {
2240 uint16_t dqo_version;
2241 uint16_t dqo_label;
2242 uint16_t dqo_label_size;
2243 } dispatch_queue_offsets;
2244
2245
2246 Error error;
2247 if (ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
2248 {
2249 uint32_t data_offset = 0;
2250 if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
2251 {
2252 if (ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
2253 {
2254 data_offset = 0;
2255 lldb::addr_t queue_addr = data.GetAddress(&data_offset);
2256 lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
2257 dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0');
2258 size_t bytes_read = ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error);
2259 if (bytes_read < dispatch_queue_offsets.dqo_label_size)
2260 dispatch_queue_name.erase (bytes_read);
2261 }
2262 }
2263 }
2264 }
2265 if (dispatch_queue_name.empty())
2266 return NULL;
2267 return dispatch_queue_name.c_str();
2268}
2269
Greg Claytone4b9c1f2011-03-08 22:40:15 +00002270//uint32_t
2271//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
2272//{
2273// // If we are planning to launch the debugserver remotely, then we need to fire up a debugserver
2274// // process and ask it for the list of processes. But if we are local, we can let the Host do it.
2275// if (m_local_debugserver)
2276// {
2277// return Host::ListProcessesMatchingName (name, matches, pids);
2278// }
2279// else
2280// {
2281// // FIXME: Implement talking to the remote debugserver.
2282// return 0;
2283// }
2284//
2285//}
2286//
Jim Ingham55e01d82011-01-22 01:33:44 +00002287bool
2288ProcessGDBRemote::NewThreadNotifyBreakpointHit (void *baton,
2289 lldb_private::StoppointCallbackContext *context,
2290 lldb::user_id_t break_id,
2291 lldb::user_id_t break_loc_id)
2292{
2293 // I don't think I have to do anything here, just make sure I notice the new thread when it starts to
2294 // run so I can stop it if that's what I want to do.
2295 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
2296 if (log)
2297 log->Printf("Hit New Thread Notification breakpoint.");
2298 return false;
2299}
2300
2301
2302bool
2303ProcessGDBRemote::StartNoticingNewThreads()
2304{
2305 static const char *bp_names[] =
2306 {
2307 "start_wqthread",
Jim Inghamff276fe2011-02-08 05:19:01 +00002308 "_pthread_wqthread",
Jim Ingham55e01d82011-01-22 01:33:44 +00002309 "_pthread_start",
2310 NULL
2311 };
2312
2313 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
2314 size_t num_bps = m_thread_observation_bps.size();
2315 if (num_bps != 0)
2316 {
2317 for (int i = 0; i < num_bps; i++)
2318 {
2319 lldb::BreakpointSP break_sp = m_target.GetBreakpointByID(m_thread_observation_bps[i]);
2320 if (break_sp)
2321 {
2322 if (log)
2323 log->Printf("Enabled noticing new thread breakpoint.");
2324 break_sp->SetEnabled(true);
2325 }
2326 }
2327 }
2328 else
2329 {
2330 for (int i = 0; bp_names[i] != NULL; i++)
2331 {
2332 Breakpoint *breakpoint = m_target.CreateBreakpoint (NULL, bp_names[i], eFunctionNameTypeFull, true).get();
2333 if (breakpoint)
2334 {
2335 if (log)
2336 log->Printf("Successfully created new thread notification breakpoint at \"%s\".", bp_names[i]);
2337 m_thread_observation_bps.push_back(breakpoint->GetID());
2338 breakpoint->SetCallback (ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
2339 }
2340 else
2341 {
2342 if (log)
2343 log->Printf("Failed to create new thread notification breakpoint.");
2344 return false;
2345 }
2346 }
2347 }
2348
2349 return true;
2350}
2351
2352bool
2353ProcessGDBRemote::StopNoticingNewThreads()
2354{
Jim Inghamff276fe2011-02-08 05:19:01 +00002355 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
2356 if (log)
2357 log->Printf ("Disabling new thread notification breakpoint.");
Jim Ingham55e01d82011-01-22 01:33:44 +00002358 size_t num_bps = m_thread_observation_bps.size();
2359 if (num_bps != 0)
2360 {
2361 for (int i = 0; i < num_bps; i++)
2362 {
Jim Ingham55e01d82011-01-22 01:33:44 +00002363
2364 lldb::BreakpointSP break_sp = m_target.GetBreakpointByID(m_thread_observation_bps[i]);
2365 if (break_sp)
2366 {
Jim Ingham55e01d82011-01-22 01:33:44 +00002367 break_sp->SetEnabled(false);
2368 }
2369 }
2370 }
2371 return true;
2372}
2373
2374