blob: 79f77e219d1f5c3e77017e02e19c92307efe8240 [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
355 if (strncmp (remote_url, "connect://", strlen ("connect://")) == 0)
356 {
357 error = ConnectToDebugserver (remote_url);
358 }
359 else
360 {
361 error.SetErrorStringWithFormat ("unsupported remote url: %s", remote_url);
362 }
363
364 if (error.Fail())
365 return error;
366 StartAsyncThread ();
367
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000368 lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
Greg Claytone71e2582011-02-04 01:58:07 +0000369 if (pid == LLDB_INVALID_PROCESS_ID)
370 {
371 // We don't have a valid process ID, so note that we are connected
372 // and could now request to launch or attach, or get remote process
373 // listings...
374 SetPrivateState (eStateConnected);
375 }
376 else
377 {
378 // We have a valid process
379 SetID (pid);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000380 UpdateThreadListIfNeeded ();
Greg Claytone71e2582011-02-04 01:58:07 +0000381 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000382 if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, response, false))
Greg Claytone71e2582011-02-04 01:58:07 +0000383 {
384 const StateType state = SetThreadStopInfo (response);
385 if (state == eStateStopped)
386 {
387 SetPrivateState (state);
388 }
389 else
390 error.SetErrorStringWithFormat ("Process %i was reported after connecting to '%s', but state was not stopped: %s", pid, remote_url, StateAsCString (state));
391 }
392 else
393 error.SetErrorStringWithFormat ("Process %i was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
394 }
395 return error;
396}
397
398Error
Chris Lattner24943d22010-06-08 16:52:24 +0000399ProcessGDBRemote::WillLaunchOrAttach ()
400{
401 Error error;
Chris Lattner24943d22010-06-08 16:52:24 +0000402 m_stdio_communication.Clear ();
Chris Lattner24943d22010-06-08 16:52:24 +0000403 return error;
404}
405
406//----------------------------------------------------------------------
407// Process Control
408//----------------------------------------------------------------------
409Error
410ProcessGDBRemote::DoLaunch
411(
412 Module* module,
413 char const *argv[],
414 char const *envp[],
Greg Clayton452bf612010-08-31 18:35:14 +0000415 uint32_t launch_flags,
Chris Lattner24943d22010-06-08 16:52:24 +0000416 const char *stdin_path,
417 const char *stdout_path,
Greg Claytonde915be2011-01-23 05:56:20 +0000418 const char *stderr_path,
419 const char *working_dir
Chris Lattner24943d22010-06-08 16:52:24 +0000420)
421{
Greg Clayton4b407112010-09-30 21:49:03 +0000422 Error error;
Chris Lattner24943d22010-06-08 16:52:24 +0000423 // ::LogSetBitMask (GDBR_LOG_DEFAULT);
424 // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
425 // ::LogSetLogFile ("/dev/stdout");
Chris Lattner24943d22010-06-08 16:52:24 +0000426
427 ObjectFile * object_file = module->GetObjectFile();
428 if (object_file)
429 {
Chris Lattner24943d22010-06-08 16:52:24 +0000430 char host_port[128];
431 snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
Greg Claytone71e2582011-02-04 01:58:07 +0000432 char connect_url[128];
433 snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
Chris Lattner24943d22010-06-08 16:52:24 +0000434
Greg Claytona2f74232011-02-24 22:24:29 +0000435 // Make sure we aren't already connected?
436 if (!m_gdb_comm.IsConnected())
Chris Lattner24943d22010-06-08 16:52:24 +0000437 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000438 error = StartDebugserverProcess (host_port);
Chris Lattner24943d22010-06-08 16:52:24 +0000439 if (error.Fail())
440 return error;
441
Greg Claytone71e2582011-02-04 01:58:07 +0000442 error = ConnectToDebugserver (connect_url);
Greg Claytona2f74232011-02-24 22:24:29 +0000443 }
444
445 if (error.Success())
446 {
447 lldb_utility::PseudoTerminal pty;
448 const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
Greg Claytonafb81862011-03-02 21:34:46 +0000449
450 // If the debugserver is local and we aren't disabling STDIO, lets use
451 // a pseudo terminal to instead of relying on the 'O' packets for stdio
452 // since 'O' packets can really slow down debugging if the inferior
453 // does a lot of output.
454 if (m_local_debugserver && !disable_stdio)
Greg Claytona2f74232011-02-24 22:24:29 +0000455 {
456 const char *slave_name = NULL;
457 if (stdin_path == NULL || stdout_path == NULL || stderr_path == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000458 {
Greg Claytona2f74232011-02-24 22:24:29 +0000459 if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
460 slave_name = pty.GetSlaveName (NULL, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000461 }
Greg Claytona2f74232011-02-24 22:24:29 +0000462 if (stdin_path == NULL)
463 stdin_path = slave_name;
Chris Lattner24943d22010-06-08 16:52:24 +0000464
Greg Claytona2f74232011-02-24 22:24:29 +0000465 if (stdout_path == NULL)
466 stdout_path = slave_name;
467
468 if (stderr_path == NULL)
469 stderr_path = slave_name;
470 }
471
Greg Claytonafb81862011-03-02 21:34:46 +0000472 // Set STDIN to /dev/null if we want STDIO disabled or if either
473 // STDOUT or STDERR have been set to something and STDIN hasn't
474 if (disable_stdio || (stdin_path == NULL && (stdout_path || stderr_path)))
Greg Claytona2f74232011-02-24 22:24:29 +0000475 stdin_path = "/dev/null";
476
Greg Claytonafb81862011-03-02 21:34:46 +0000477 // Set STDOUT to /dev/null if we want STDIO disabled or if either
478 // STDIN or STDERR have been set to something and STDOUT hasn't
479 if (disable_stdio || (stdout_path == NULL && (stdin_path || stderr_path)))
Greg Claytona2f74232011-02-24 22:24:29 +0000480 stdout_path = "/dev/null";
481
Greg Claytonafb81862011-03-02 21:34:46 +0000482 // Set STDERR to /dev/null if we want STDIO disabled or if either
483 // STDIN or STDOUT have been set to something and STDERR hasn't
484 if (disable_stdio || (stderr_path == NULL && (stdin_path || stdout_path)))
Greg Claytona2f74232011-02-24 22:24:29 +0000485 stderr_path = "/dev/null";
486
487 if (stdin_path)
488 m_gdb_comm.SetSTDIN (stdin_path);
489 if (stdout_path)
490 m_gdb_comm.SetSTDOUT (stdout_path);
491 if (stderr_path)
492 m_gdb_comm.SetSTDERR (stderr_path);
493
494 m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
495
496
497 if (working_dir && working_dir[0])
498 {
499 m_gdb_comm.SetWorkingDir (working_dir);
500 }
501
502 // Send the environment and the program + arguments after we connect
503 if (envp)
504 {
505 const char *env_entry;
506 for (int i=0; (env_entry = envp[i]); ++i)
Greg Clayton960d6a42010-08-03 00:35:52 +0000507 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000508 if (m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
Greg Claytona2f74232011-02-24 22:24:29 +0000509 break;
Greg Clayton960d6a42010-08-03 00:35:52 +0000510 }
Greg Claytona2f74232011-02-24 22:24:29 +0000511 }
Greg Clayton960d6a42010-08-03 00:35:52 +0000512
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000513 const uint32_t old_packet_timeout = m_gdb_comm.SetPacketTimeout (10);
514 int arg_packet_err = m_gdb_comm.SendArgumentsPacket (argv);
515 m_gdb_comm.SetPacketTimeout (old_packet_timeout);
Greg Claytona2f74232011-02-24 22:24:29 +0000516 if (arg_packet_err == 0)
517 {
518 std::string error_str;
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000519 if (m_gdb_comm.GetLaunchSuccess (error_str))
Chris Lattner24943d22010-06-08 16:52:24 +0000520 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000521 SetID (m_gdb_comm.GetCurrentProcessID ());
Chris Lattner24943d22010-06-08 16:52:24 +0000522 }
523 else
524 {
Greg Claytona2f74232011-02-24 22:24:29 +0000525 error.SetErrorString (error_str.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000526 }
Greg Claytona2f74232011-02-24 22:24:29 +0000527 }
528 else
529 {
530 error.SetErrorStringWithFormat("'A' packet returned an error: %i.\n", arg_packet_err);
531 }
Chris Lattner24943d22010-06-08 16:52:24 +0000532
Greg Claytona2f74232011-02-24 22:24:29 +0000533 if (GetID() == LLDB_INVALID_PROCESS_ID)
534 {
535 KillDebugserverProcess ();
536 return error;
537 }
538
539 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000540 if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, response, false))
Greg Claytona2f74232011-02-24 22:24:29 +0000541 {
542 SetPrivateState (SetThreadStopInfo (response));
543
544 if (!disable_stdio)
545 {
546 if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd)
547 SetUpProcessInputReader (pty.ReleaseMasterFileDescriptor());
548 }
Chris Lattner24943d22010-06-08 16:52:24 +0000549 }
550 }
Chris Lattner24943d22010-06-08 16:52:24 +0000551 }
552 else
553 {
554 // Set our user ID to an invalid process ID.
555 SetID(LLDB_INVALID_PROCESS_ID);
Greg Clayton940b1032011-02-23 00:35:02 +0000556 error.SetErrorStringWithFormat("Failed to get object file from '%s' for arch %s.\n",
557 module->GetFileSpec().GetFilename().AsCString(),
558 module->GetArchitecture().GetArchitectureName());
Chris Lattner24943d22010-06-08 16:52:24 +0000559 }
Chris Lattner24943d22010-06-08 16:52:24 +0000560 return error;
Greg Clayton4b407112010-09-30 21:49:03 +0000561
Chris Lattner24943d22010-06-08 16:52:24 +0000562}
563
564
565Error
Greg Claytone71e2582011-02-04 01:58:07 +0000566ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
Chris Lattner24943d22010-06-08 16:52:24 +0000567{
568 Error error;
569 // Sleep and wait a bit for debugserver to start to listen...
570 std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
571 if (conn_ap.get())
572 {
Chris Lattner24943d22010-06-08 16:52:24 +0000573 const uint32_t max_retry_count = 50;
574 uint32_t retry_count = 0;
575 while (!m_gdb_comm.IsConnected())
576 {
Greg Claytone71e2582011-02-04 01:58:07 +0000577 if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
Chris Lattner24943d22010-06-08 16:52:24 +0000578 {
579 m_gdb_comm.SetConnection (conn_ap.release());
580 break;
581 }
582 retry_count++;
583
584 if (retry_count >= max_retry_count)
585 break;
586
587 usleep (100000);
588 }
589 }
590
591 if (!m_gdb_comm.IsConnected())
592 {
593 if (error.Success())
594 error.SetErrorString("not connected to remote gdb server");
595 return error;
596 }
597
Greg Clayton24bc5d92011-03-30 18:16:51 +0000598 // We always seem to be able to open a connection to a local port
599 // so we need to make sure we can then send data to it. If we can't
600 // then we aren't actually connected to anything, so try and do the
601 // handshake with the remote GDB server and make sure that goes
602 // alright.
603 if (!m_gdb_comm.HandshakeWithServer (NULL))
Chris Lattner24943d22010-06-08 16:52:24 +0000604 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000605 m_gdb_comm.Disconnect();
606 if (error.Success())
607 error.SetErrorString("not connected to remote gdb server");
608 return error;
Chris Lattner24943d22010-06-08 16:52:24 +0000609 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000610 if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
611 m_debugserver_thread = Host::StartMonitoringChildProcess (MonitorDebugserverProcess,
612 this,
613 m_debugserver_pid,
614 false);
615 m_gdb_comm.ResetDiscoverableSettings();
616 m_gdb_comm.QueryNoAckModeSupported ();
617 m_gdb_comm.GetThreadSuffixSupported ();
618 m_gdb_comm.GetHostInfo ();
619 m_gdb_comm.GetVContSupported ('c');
Chris Lattner24943d22010-06-08 16:52:24 +0000620 return error;
621}
622
623void
624ProcessGDBRemote::DidLaunchOrAttach ()
625{
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000626 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
627 if (log)
628 log->Printf ("ProcessGDBRemote::DidLaunch()");
Greg Clayton75c703d2011-02-16 04:46:07 +0000629 if (GetID() != LLDB_INVALID_PROCESS_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000630 {
631 m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
632
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000633 BuildDynamicRegisterInfo (false);
Greg Clayton20d338f2010-11-18 05:57:03 +0000634
Chris Lattner24943d22010-06-08 16:52:24 +0000635 // See if the GDB server supports the qHostInfo information
Greg Claytonfc7920f2011-02-09 03:09:55 +0000636
Greg Claytoncb8977d2011-03-23 00:09:55 +0000637 const ArchSpec &gdb_remote_arch = m_gdb_comm.GetHostArchitecture();
638 if (gdb_remote_arch.IsValid())
Greg Claytonfc7920f2011-02-09 03:09:55 +0000639 {
Greg Claytoncb8977d2011-03-23 00:09:55 +0000640 ArchSpec &target_arch = GetTarget().GetArchitecture();
641
642 if (target_arch.IsValid())
643 {
644 // If the remote host is ARM and we have apple as the vendor, then
645 // ARM executables and shared libraries can have mixed ARM architectures.
646 // You can have an armv6 executable, and if the host is armv7, then the
647 // system will load the best possible architecture for all shared libraries
648 // it has, so we really need to take the remote host architecture as our
649 // defacto architecture in this case.
650
651 if (gdb_remote_arch.GetMachine() == llvm::Triple::arm &&
652 gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
653 {
654 target_arch = gdb_remote_arch;
655 }
656 else
657 {
658 // Fill in what is missing in the triple
659 const llvm::Triple &remote_triple = gdb_remote_arch.GetTriple();
660 llvm::Triple &target_triple = target_arch.GetTriple();
661 if (target_triple.getVendor() == llvm::Triple::UnknownVendor)
662 target_triple.setVendor (remote_triple.getVendor());
663
664 if (target_triple.getOS() == llvm::Triple::UnknownOS)
665 target_triple.setOS (remote_triple.getOS());
666
667 if (target_triple.getEnvironment() == llvm::Triple::UnknownEnvironment)
668 target_triple.setEnvironment (remote_triple.getEnvironment());
669 }
670 }
671 else
672 {
673 // The target doesn't have a valid architecture yet, set it from
674 // the architecture we got from the remote GDB server
675 target_arch = gdb_remote_arch;
676 }
Greg Claytonfc7920f2011-02-09 03:09:55 +0000677 }
Chris Lattner24943d22010-06-08 16:52:24 +0000678 }
679}
680
681void
682ProcessGDBRemote::DidLaunch ()
683{
684 DidLaunchOrAttach ();
Chris Lattner24943d22010-06-08 16:52:24 +0000685}
686
687Error
Greg Clayton54e7afa2010-07-09 20:39:50 +0000688ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
Chris Lattner24943d22010-06-08 16:52:24 +0000689{
690 Error error;
691 // Clear out and clean up from any current state
692 Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000693 if (attach_pid != LLDB_INVALID_PROCESS_ID)
694 {
Greg Claytona2f74232011-02-24 22:24:29 +0000695 // Make sure we aren't already connected?
696 if (!m_gdb_comm.IsConnected())
Chris Lattner24943d22010-06-08 16:52:24 +0000697 {
Greg Claytona2f74232011-02-24 22:24:29 +0000698 char host_port[128];
699 snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
700 char connect_url[128];
701 snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
Chris Lattner24943d22010-06-08 16:52:24 +0000702
Greg Claytonb72d0f02011-04-12 05:54:46 +0000703 error = StartDebugserverProcess (host_port);
Greg Claytona2f74232011-02-24 22:24:29 +0000704
705 if (error.Fail())
Chris Lattner24943d22010-06-08 16:52:24 +0000706 {
Greg Claytona2f74232011-02-24 22:24:29 +0000707 const char *error_string = error.AsCString();
708 if (error_string == NULL)
709 error_string = "unable to launch " DEBUGSERVER_BASENAME;
710
711 SetExitStatus (-1, error_string);
Chris Lattner24943d22010-06-08 16:52:24 +0000712 }
Greg Claytona2f74232011-02-24 22:24:29 +0000713 else
714 {
715 error = ConnectToDebugserver (connect_url);
716 }
717 }
718
719 if (error.Success())
720 {
721 char packet[64];
722 const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%x", attach_pid);
723
724 m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
Chris Lattner24943d22010-06-08 16:52:24 +0000725 }
726 }
Chris Lattner24943d22010-06-08 16:52:24 +0000727 return error;
728}
729
730size_t
731ProcessGDBRemote::AttachInputReaderCallback
732(
733 void *baton,
734 InputReader *reader,
735 lldb::InputReaderAction notification,
736 const char *bytes,
737 size_t bytes_len
738)
739{
740 if (notification == eInputReaderGotToken)
741 {
742 ProcessGDBRemote *gdb_process = (ProcessGDBRemote *)baton;
743 if (gdb_process->m_waiting_for_attach)
744 gdb_process->m_waiting_for_attach = false;
745 reader->SetIsDone(true);
746 return 1;
747 }
748 return 0;
749}
750
751Error
Greg Clayton54e7afa2010-07-09 20:39:50 +0000752ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait_for_launch)
Chris Lattner24943d22010-06-08 16:52:24 +0000753{
754 Error error;
755 // Clear out and clean up from any current state
756 Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000757
Chris Lattner24943d22010-06-08 16:52:24 +0000758 if (process_name && process_name[0])
759 {
Greg Claytona2f74232011-02-24 22:24:29 +0000760 // Make sure we aren't already connected?
761 if (!m_gdb_comm.IsConnected())
Chris Lattner24943d22010-06-08 16:52:24 +0000762 {
Greg Claytona2f74232011-02-24 22:24:29 +0000763 char host_port[128];
764 snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
765 char connect_url[128];
766 snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
767
Greg Claytonb72d0f02011-04-12 05:54:46 +0000768 error = StartDebugserverProcess (host_port);
Greg Claytona2f74232011-02-24 22:24:29 +0000769 if (error.Fail())
Chris Lattner24943d22010-06-08 16:52:24 +0000770 {
Greg Claytona2f74232011-02-24 22:24:29 +0000771 const char *error_string = error.AsCString();
772 if (error_string == NULL)
773 error_string = "unable to launch " DEBUGSERVER_BASENAME;
Chris Lattner24943d22010-06-08 16:52:24 +0000774
Greg Claytona2f74232011-02-24 22:24:29 +0000775 SetExitStatus (-1, error_string);
Chris Lattner24943d22010-06-08 16:52:24 +0000776 }
Greg Claytona2f74232011-02-24 22:24:29 +0000777 else
778 {
779 error = ConnectToDebugserver (connect_url);
780 }
781 }
782
783 if (error.Success())
784 {
785 StreamString packet;
786
787 if (wait_for_launch)
788 packet.PutCString("vAttachWait");
789 else
790 packet.PutCString("vAttachName");
791 packet.PutChar(';');
792 packet.PutBytesAsRawHex8(process_name, strlen(process_name), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
793
794 m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));
795
Chris Lattner24943d22010-06-08 16:52:24 +0000796 }
797 }
Chris Lattner24943d22010-06-08 16:52:24 +0000798 return error;
799}
800
Chris Lattner24943d22010-06-08 16:52:24 +0000801
802void
803ProcessGDBRemote::DidAttach ()
804{
Greg Claytone71e2582011-02-04 01:58:07 +0000805 DidLaunchOrAttach ();
Chris Lattner24943d22010-06-08 16:52:24 +0000806}
807
808Error
809ProcessGDBRemote::WillResume ()
810{
Greg Claytonc1f45872011-02-12 06:28:37 +0000811 m_continue_c_tids.clear();
812 m_continue_C_tids.clear();
813 m_continue_s_tids.clear();
814 m_continue_S_tids.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000815 return Error();
816}
817
818Error
819ProcessGDBRemote::DoResume ()
820{
Jim Ingham3ae449a2010-11-17 02:32:00 +0000821 Error error;
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000822 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
823 if (log)
824 log->Printf ("ProcessGDBRemote::Resume()");
Greg Claytonb749a262010-12-03 06:02:24 +0000825
826 Listener listener ("gdb-remote.resume-packet-sent");
827 if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
828 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000829 StreamString continue_packet;
830 bool continue_packet_error = false;
831 if (m_gdb_comm.HasAnyVContSupport ())
832 {
833 continue_packet.PutCString ("vCont");
834
835 if (!m_continue_c_tids.empty())
836 {
837 if (m_gdb_comm.GetVContSupported ('c'))
838 {
839 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)
840 continue_packet.Printf(";c:%4.4x", *t_pos);
841 }
842 else
843 continue_packet_error = true;
844 }
845
846 if (!continue_packet_error && !m_continue_C_tids.empty())
847 {
848 if (m_gdb_comm.GetVContSupported ('C'))
849 {
850 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)
851 continue_packet.Printf(";C%2.2x:%4.4x", s_pos->second, s_pos->first);
852 }
853 else
854 continue_packet_error = true;
855 }
Greg Claytonb749a262010-12-03 06:02:24 +0000856
Greg Claytonc1f45872011-02-12 06:28:37 +0000857 if (!continue_packet_error && !m_continue_s_tids.empty())
858 {
859 if (m_gdb_comm.GetVContSupported ('s'))
860 {
861 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)
862 continue_packet.Printf(";s:%4.4x", *t_pos);
863 }
864 else
865 continue_packet_error = true;
866 }
867
868 if (!continue_packet_error && !m_continue_S_tids.empty())
869 {
870 if (m_gdb_comm.GetVContSupported ('S'))
871 {
872 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)
873 continue_packet.Printf(";S%2.2x:%4.4x", s_pos->second, s_pos->first);
874 }
875 else
876 continue_packet_error = true;
877 }
878
879 if (continue_packet_error)
880 continue_packet.GetString().clear();
881 }
882 else
883 continue_packet_error = true;
884
885 if (continue_packet_error)
886 {
887 continue_packet_error = false;
888 // Either no vCont support, or we tried to use part of the vCont
889 // packet that wasn't supported by the remote GDB server.
890 // We need to try and make a simple packet that can do our continue
891 const size_t num_threads = GetThreadList().GetSize();
892 const size_t num_continue_c_tids = m_continue_c_tids.size();
893 const size_t num_continue_C_tids = m_continue_C_tids.size();
894 const size_t num_continue_s_tids = m_continue_s_tids.size();
895 const size_t num_continue_S_tids = m_continue_S_tids.size();
896 if (num_continue_c_tids > 0)
897 {
898 if (num_continue_c_tids == num_threads)
899 {
900 // All threads are resuming...
Greg Claytonb72d0f02011-04-12 05:54:46 +0000901 m_gdb_comm.SetCurrentThreadForRun (-1);
Greg Claytonc1f45872011-02-12 06:28:37 +0000902 continue_packet.PutChar ('c');
903 }
904 else if (num_continue_c_tids == 1 &&
905 num_continue_C_tids == 0 &&
906 num_continue_s_tids == 0 &&
907 num_continue_S_tids == 0 )
908 {
909 // Only one thread is continuing
Greg Claytonb72d0f02011-04-12 05:54:46 +0000910 m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
Greg Claytonc1f45872011-02-12 06:28:37 +0000911 continue_packet.PutChar ('c');
912 }
913 else
914 {
915 // We can't represent this continue packet....
916 continue_packet_error = true;
917 }
918 }
919
920 if (!continue_packet_error && num_continue_C_tids > 0)
921 {
922 if (num_continue_C_tids == num_threads)
923 {
924 const int continue_signo = m_continue_C_tids.front().second;
925 if (num_continue_C_tids > 1)
926 {
927 for (size_t i=1; i<num_threads; ++i)
928 {
929 if (m_continue_C_tids[i].second != continue_signo)
930 continue_packet_error = true;
931 }
932 }
933 if (!continue_packet_error)
934 {
935 // Add threads continuing with the same signo...
Greg Claytonb72d0f02011-04-12 05:54:46 +0000936 m_gdb_comm.SetCurrentThreadForRun (-1);
Greg Claytonc1f45872011-02-12 06:28:37 +0000937 continue_packet.Printf("C%2.2x", continue_signo);
938 }
939 }
940 else if (num_continue_c_tids == 0 &&
941 num_continue_C_tids == 1 &&
942 num_continue_s_tids == 0 &&
943 num_continue_S_tids == 0 )
944 {
945 // Only one thread is continuing with signal
Greg Claytonb72d0f02011-04-12 05:54:46 +0000946 m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first);
Greg Claytonc1f45872011-02-12 06:28:37 +0000947 continue_packet.Printf("C%2.2x", m_continue_C_tids.front().second);
948 }
949 else
950 {
951 // We can't represent this continue packet....
952 continue_packet_error = true;
953 }
954 }
955
956 if (!continue_packet_error && num_continue_s_tids > 0)
957 {
958 if (num_continue_s_tids == num_threads)
959 {
960 // All threads are resuming...
Greg Claytonb72d0f02011-04-12 05:54:46 +0000961 m_gdb_comm.SetCurrentThreadForRun (-1);
Greg Claytonc1f45872011-02-12 06:28:37 +0000962 continue_packet.PutChar ('s');
963 }
964 else if (num_continue_c_tids == 0 &&
965 num_continue_C_tids == 0 &&
966 num_continue_s_tids == 1 &&
967 num_continue_S_tids == 0 )
968 {
969 // Only one thread is stepping
Greg Claytonb72d0f02011-04-12 05:54:46 +0000970 m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
Greg Claytonc1f45872011-02-12 06:28:37 +0000971 continue_packet.PutChar ('s');
972 }
973 else
974 {
975 // We can't represent this continue packet....
976 continue_packet_error = true;
977 }
978 }
979
980 if (!continue_packet_error && num_continue_S_tids > 0)
981 {
982 if (num_continue_S_tids == num_threads)
983 {
984 const int step_signo = m_continue_S_tids.front().second;
985 // Are all threads trying to step with the same signal?
986 if (num_continue_S_tids > 1)
987 {
988 for (size_t i=1; i<num_threads; ++i)
989 {
990 if (m_continue_S_tids[i].second != step_signo)
991 continue_packet_error = true;
992 }
993 }
994 if (!continue_packet_error)
995 {
996 // Add threads stepping with the same signo...
Greg Claytonb72d0f02011-04-12 05:54:46 +0000997 m_gdb_comm.SetCurrentThreadForRun (-1);
Greg Claytonc1f45872011-02-12 06:28:37 +0000998 continue_packet.Printf("S%2.2x", step_signo);
999 }
1000 }
1001 else if (num_continue_c_tids == 0 &&
1002 num_continue_C_tids == 0 &&
1003 num_continue_s_tids == 0 &&
1004 num_continue_S_tids == 1 )
1005 {
1006 // Only one thread is stepping with signal
Greg Claytonb72d0f02011-04-12 05:54:46 +00001007 m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first);
Greg Claytonc1f45872011-02-12 06:28:37 +00001008 continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
1009 }
1010 else
1011 {
1012 // We can't represent this continue packet....
1013 continue_packet_error = true;
1014 }
1015 }
1016 }
1017
1018 if (continue_packet_error)
1019 {
1020 error.SetErrorString ("can't make continue packet for this resume");
1021 }
1022 else
1023 {
1024 EventSP event_sp;
1025 TimeValue timeout;
1026 timeout = TimeValue::Now();
1027 timeout.OffsetWithSeconds (5);
1028 m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
1029
1030 if (listener.WaitForEvent (&timeout, event_sp) == false)
1031 error.SetErrorString("Resume timed out.");
1032 }
Greg Claytonb749a262010-12-03 06:02:24 +00001033 }
1034
Jim Ingham3ae449a2010-11-17 02:32:00 +00001035 return error;
Chris Lattner24943d22010-06-08 16:52:24 +00001036}
1037
Chris Lattner24943d22010-06-08 16:52:24 +00001038uint32_t
1039ProcessGDBRemote::UpdateThreadListIfNeeded ()
1040{
1041 // locker will keep a mutex locked until it goes out of scope
Greg Claytone005f2c2010-11-06 01:53:30 +00001042 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
Greg Claytonf3d0b0c2010-10-27 03:32:59 +00001043 if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
Chris Lattner24943d22010-06-08 16:52:24 +00001044 log->Printf ("ProcessGDBRemote::%s (pid = %i)", __FUNCTION__, GetID());
1045
Greg Clayton5205f0b2010-09-03 17:10:42 +00001046 Mutex::Locker locker (m_thread_list.GetMutex ());
Chris Lattner24943d22010-06-08 16:52:24 +00001047 const uint32_t stop_id = GetStopID();
1048 if (m_thread_list.GetSize(false) == 0 || stop_id != m_thread_list.GetStopID())
1049 {
1050 // Update the thread list's stop id immediately so we don't recurse into this function.
1051 ThreadList curr_thread_list (this);
1052 curr_thread_list.SetStopID(stop_id);
1053
1054 Error err;
1055 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001056 for (m_gdb_comm.SendPacketAndWaitForResponse("qfThreadInfo", response, false);
Greg Clayton61d043b2011-03-22 04:00:09 +00001057 response.IsNormalResponse();
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001058 m_gdb_comm.SendPacketAndWaitForResponse("qsThreadInfo", response, false))
Chris Lattner24943d22010-06-08 16:52:24 +00001059 {
1060 char ch = response.GetChar();
1061 if (ch == 'l')
1062 break;
1063 if (ch == 'm')
1064 {
1065 do
1066 {
1067 tid_t tid = response.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
1068
1069 if (tid != LLDB_INVALID_THREAD_ID)
1070 {
1071 ThreadSP thread_sp (GetThreadList().FindThreadByID (tid, false));
Greg Claytona875b642011-01-09 21:07:35 +00001072 if (!thread_sp)
Chris Lattner24943d22010-06-08 16:52:24 +00001073 thread_sp.reset (new ThreadGDBRemote (*this, tid));
1074 curr_thread_list.AddThread(thread_sp);
1075 }
1076
1077 ch = response.GetChar();
1078 } while (ch == ',');
1079 }
1080 }
1081
1082 m_thread_list = curr_thread_list;
1083
1084 SetThreadStopInfo (m_last_stop_packet);
1085 }
1086 return GetThreadList().GetSize(false);
1087}
1088
1089
1090StateType
1091ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
1092{
1093 const char stop_type = stop_packet.GetChar();
1094 switch (stop_type)
1095 {
1096 case 'T':
1097 case 'S':
1098 {
Greg Claytonc3c46612011-02-15 00:19:15 +00001099 if (GetStopID() == 0)
1100 {
1101 // Our first stop, make sure we have a process ID, and also make
1102 // sure we know about our registers
1103 if (GetID() == LLDB_INVALID_PROCESS_ID)
1104 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001105 lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
Greg Claytonc3c46612011-02-15 00:19:15 +00001106 if (pid != LLDB_INVALID_PROCESS_ID)
1107 SetID (pid);
1108 }
1109 BuildDynamicRegisterInfo (true);
1110 }
Chris Lattner24943d22010-06-08 16:52:24 +00001111 // Stop with signal and thread info
1112 const uint8_t signo = stop_packet.GetHexU8();
1113 std::string name;
1114 std::string value;
1115 std::string thread_name;
1116 uint32_t exc_type = 0;
Greg Clayton7661a982010-07-23 16:45:51 +00001117 std::vector<addr_t> exc_data;
Chris Lattner24943d22010-06-08 16:52:24 +00001118 uint32_t tid = LLDB_INVALID_THREAD_ID;
1119 addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
1120 uint32_t exc_data_count = 0;
Greg Claytona875b642011-01-09 21:07:35 +00001121 ThreadSP thread_sp;
1122
Chris Lattner24943d22010-06-08 16:52:24 +00001123 while (stop_packet.GetNameColonValue(name, value))
1124 {
1125 if (name.compare("metype") == 0)
1126 {
1127 // exception type in big endian hex
1128 exc_type = Args::StringToUInt32 (value.c_str(), 0, 16);
1129 }
1130 else if (name.compare("mecount") == 0)
1131 {
1132 // exception count in big endian hex
1133 exc_data_count = Args::StringToUInt32 (value.c_str(), 0, 16);
1134 }
1135 else if (name.compare("medata") == 0)
1136 {
1137 // exception data in big endian hex
1138 exc_data.push_back(Args::StringToUInt64 (value.c_str(), 0, 16));
1139 }
1140 else if (name.compare("thread") == 0)
1141 {
1142 // thread in big endian hex
1143 tid = Args::StringToUInt32 (value.c_str(), 0, 16);
Greg Claytonc3c46612011-02-15 00:19:15 +00001144 Mutex::Locker locker (m_thread_list.GetMutex ());
Greg Claytona875b642011-01-09 21:07:35 +00001145 thread_sp = m_thread_list.FindThreadByID(tid, false);
Greg Claytonc3c46612011-02-15 00:19:15 +00001146 if (!thread_sp)
1147 {
1148 // Create the thread if we need to
1149 thread_sp.reset (new ThreadGDBRemote (*this, tid));
1150 m_thread_list.AddThread(thread_sp);
1151 }
Chris Lattner24943d22010-06-08 16:52:24 +00001152 }
Greg Clayton4862fa22011-01-08 03:17:57 +00001153 else if (name.compare("hexname") == 0)
1154 {
1155 StringExtractor name_extractor;
1156 // Swap "value" over into "name_extractor"
1157 name_extractor.GetStringRef().swap(value);
1158 // Now convert the HEX bytes into a string value
1159 name_extractor.GetHexByteString (value);
1160 thread_name.swap (value);
1161 }
Chris Lattner24943d22010-06-08 16:52:24 +00001162 else if (name.compare("name") == 0)
1163 {
1164 thread_name.swap (value);
1165 }
Greg Clayton0a7f75f2010-09-09 06:32:46 +00001166 else if (name.compare("qaddr") == 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001167 {
1168 thread_dispatch_qaddr = Args::StringToUInt64 (value.c_str(), 0, 16);
1169 }
Greg Claytona875b642011-01-09 21:07:35 +00001170 else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1]))
1171 {
1172 // We have a register number that contains an expedited
1173 // register value. Lets supply this register to our thread
1174 // so it won't have to go and read it.
1175 if (thread_sp)
1176 {
1177 uint32_t reg = Args::StringToUInt32 (name.c_str(), UINT32_MAX, 16);
1178
1179 if (reg != UINT32_MAX)
1180 {
1181 StringExtractor reg_value_extractor;
1182 // Swap "value" over into "reg_value_extractor"
1183 reg_value_extractor.GetStringRef().swap(value);
Greg Claytonc3c46612011-02-15 00:19:15 +00001184 if (!static_cast<ThreadGDBRemote *> (thread_sp.get())->PrivateSetRegisterValue (reg, reg_value_extractor))
1185 {
1186 Host::SetCrashDescriptionWithFormat("Setting thread register '%s' (decoded to %u (0x%x)) with value '%s' for stop packet: '%s'",
1187 name.c_str(),
1188 reg,
1189 reg,
1190 reg_value_extractor.GetStringRef().c_str(),
1191 stop_packet.GetStringRef().c_str());
1192 }
Greg Claytona875b642011-01-09 21:07:35 +00001193 }
1194 }
1195 }
Chris Lattner24943d22010-06-08 16:52:24 +00001196 }
Chris Lattner24943d22010-06-08 16:52:24 +00001197
1198 if (thread_sp)
1199 {
1200 ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
1201
1202 gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
Jim Ingham9082c8a2011-01-28 02:23:12 +00001203 gdb_thread->SetName (thread_name.empty() ? NULL : thread_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001204 if (exc_type != 0)
1205 {
Greg Claytonbdcb6ab2011-01-25 23:55:37 +00001206 const size_t exc_data_size = exc_data.size();
Greg Clayton643ee732010-08-04 01:40:35 +00001207
1208 gdb_thread->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
1209 exc_type,
Greg Claytonbdcb6ab2011-01-25 23:55:37 +00001210 exc_data_size,
1211 exc_data_size >= 1 ? exc_data[0] : 0,
1212 exc_data_size >= 2 ? exc_data[1] : 0));
Chris Lattner24943d22010-06-08 16:52:24 +00001213 }
1214 else if (signo)
1215 {
Greg Clayton643ee732010-08-04 01:40:35 +00001216 gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo));
Chris Lattner24943d22010-06-08 16:52:24 +00001217 }
1218 else
1219 {
Greg Clayton643ee732010-08-04 01:40:35 +00001220 StopInfoSP invalid_stop_info_sp;
1221 gdb_thread->SetStopInfo (invalid_stop_info_sp);
Chris Lattner24943d22010-06-08 16:52:24 +00001222 }
1223 }
1224 return eStateStopped;
1225 }
1226 break;
1227
1228 case 'W':
1229 // process exited
1230 return eStateExited;
1231
1232 default:
1233 break;
1234 }
1235 return eStateInvalid;
1236}
1237
1238void
1239ProcessGDBRemote::RefreshStateAfterStop ()
1240{
Jim Ingham7508e732010-08-09 23:31:02 +00001241 // FIXME - add a variable to tell that we're in the middle of attaching if we
1242 // need to know that.
Chris Lattner24943d22010-06-08 16:52:24 +00001243 // We must be attaching if we don't already have a valid architecture
Jim Ingham7508e732010-08-09 23:31:02 +00001244// if (!GetTarget().GetArchitecture().IsValid())
1245// {
1246// Module *exe_module = GetTarget().GetExecutableModule().get();
1247// if (exe_module)
1248// m_arch_spec = exe_module->GetArchitecture();
1249// }
1250
Chris Lattner24943d22010-06-08 16:52:24 +00001251 // Let all threads recover from stopping and do any clean up based
1252 // on the previous thread state (if any).
1253 m_thread_list.RefreshStateAfterStop();
1254
1255 // Discover new threads:
1256 UpdateThreadListIfNeeded ();
1257}
1258
1259Error
Jim Ingham3ae449a2010-11-17 02:32:00 +00001260ProcessGDBRemote::DoHalt (bool &caused_stop)
Chris Lattner24943d22010-06-08 16:52:24 +00001261{
1262 Error error;
Jim Ingham3ae449a2010-11-17 02:32:00 +00001263
Greg Claytona4881d02011-01-22 07:12:45 +00001264 bool timed_out = false;
1265 Mutex::Locker locker;
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001266
1267 if (m_public_state.GetValue() == eStateAttaching)
Greg Clayton20d338f2010-11-18 05:57:03 +00001268 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001269 // We are being asked to halt during an attach. We need to just close
1270 // our file handle and debugserver will go away, and we can be done...
1271 m_gdb_comm.Disconnect();
Greg Clayton20d338f2010-11-18 05:57:03 +00001272 }
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001273 else
1274 {
1275 if (!m_gdb_comm.SendInterrupt (locker, 2, caused_stop, timed_out))
1276 {
1277 if (timed_out)
1278 error.SetErrorString("timed out sending interrupt packet");
1279 else
1280 error.SetErrorString("unknown error sending interrupt packet");
1281 }
1282 }
Chris Lattner24943d22010-06-08 16:52:24 +00001283 return error;
1284}
1285
1286Error
Greg Clayton72e1c782011-01-22 23:43:18 +00001287ProcessGDBRemote::InterruptIfRunning
1288(
1289 bool discard_thread_plans,
1290 bool catch_stop_event,
Greg Clayton72e1c782011-01-22 23:43:18 +00001291 EventSP &stop_event_sp
1292)
Chris Lattner24943d22010-06-08 16:52:24 +00001293{
1294 Error error;
Chris Lattner24943d22010-06-08 16:52:24 +00001295
Greg Clayton2860ba92011-01-23 19:58:49 +00001296 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
1297
Greg Clayton68ca8232011-01-25 02:58:48 +00001298 bool paused_private_state_thread = false;
Greg Clayton2860ba92011-01-23 19:58:49 +00001299 const bool is_running = m_gdb_comm.IsRunning();
1300 if (log)
Greg Clayton68ca8232011-01-25 02:58:48 +00001301 log->Printf ("ProcessGDBRemote::InterruptIfRunning(discard_thread_plans=%i, catch_stop_event=%i) is_running=%i",
Greg Clayton2860ba92011-01-23 19:58:49 +00001302 discard_thread_plans,
Greg Clayton68ca8232011-01-25 02:58:48 +00001303 catch_stop_event,
Greg Clayton2860ba92011-01-23 19:58:49 +00001304 is_running);
1305
Greg Clayton2860ba92011-01-23 19:58:49 +00001306 if (discard_thread_plans)
1307 {
1308 if (log)
1309 log->Printf ("ProcessGDBRemote::InterruptIfRunning() discarding all thread plans");
1310 m_thread_list.DiscardThreadPlans();
1311 }
1312 if (is_running)
Greg Clayton4fb400f2010-09-27 21:07:38 +00001313 {
Greg Clayton68ca8232011-01-25 02:58:48 +00001314 if (catch_stop_event)
1315 {
1316 if (log)
1317 log->Printf ("ProcessGDBRemote::InterruptIfRunning() pausing private state thread");
1318 PausePrivateStateThread();
1319 paused_private_state_thread = true;
1320 }
1321
Greg Clayton4fb400f2010-09-27 21:07:38 +00001322 bool timed_out = false;
Greg Claytona4881d02011-01-22 07:12:45 +00001323 bool sent_interrupt = false;
Greg Clayton4fb400f2010-09-27 21:07:38 +00001324 Mutex::Locker locker;
Greg Clayton72e1c782011-01-22 23:43:18 +00001325
Greg Clayton72e1c782011-01-22 23:43:18 +00001326 if (!m_gdb_comm.SendInterrupt (locker, 1, sent_interrupt, timed_out))
Greg Clayton4fb400f2010-09-27 21:07:38 +00001327 {
1328 if (timed_out)
1329 error.SetErrorString("timed out sending interrupt packet");
1330 else
1331 error.SetErrorString("unknown error sending interrupt packet");
Greg Clayton68ca8232011-01-25 02:58:48 +00001332 if (paused_private_state_thread)
Greg Clayton72e1c782011-01-22 23:43:18 +00001333 ResumePrivateStateThread();
1334 return error;
Greg Clayton4fb400f2010-09-27 21:07:38 +00001335 }
Greg Clayton72e1c782011-01-22 23:43:18 +00001336
Greg Clayton72e1c782011-01-22 23:43:18 +00001337 if (catch_stop_event)
1338 {
Greg Clayton68ca8232011-01-25 02:58:48 +00001339 // LISTEN HERE
Greg Clayton72e1c782011-01-22 23:43:18 +00001340 TimeValue timeout_time;
1341 timeout_time = TimeValue::Now();
Greg Clayton68ca8232011-01-25 02:58:48 +00001342 timeout_time.OffsetWithSeconds(5);
1343 StateType state = WaitForStateChangedEventsPrivate (&timeout_time, stop_event_sp);
Greg Clayton2860ba92011-01-23 19:58:49 +00001344
Greg Claytonbdcb6ab2011-01-25 23:55:37 +00001345 timed_out = state == eStateInvalid;
Greg Clayton2860ba92011-01-23 19:58:49 +00001346 if (log)
1347 log->Printf ("ProcessGDBRemote::InterruptIfRunning() catch stop event: state = %s, timed-out=%i", StateAsCString(state), timed_out);
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001348
Greg Clayton2860ba92011-01-23 19:58:49 +00001349 if (timed_out)
Greg Clayton72e1c782011-01-22 23:43:18 +00001350 error.SetErrorString("unable to verify target stopped");
1351 }
1352
Greg Clayton68ca8232011-01-25 02:58:48 +00001353 if (paused_private_state_thread)
Greg Clayton2860ba92011-01-23 19:58:49 +00001354 {
1355 if (log)
1356 log->Printf ("ProcessGDBRemote::InterruptIfRunning() resuming private state thread");
Greg Clayton72e1c782011-01-22 23:43:18 +00001357 ResumePrivateStateThread();
Greg Clayton2860ba92011-01-23 19:58:49 +00001358 }
Greg Clayton4fb400f2010-09-27 21:07:38 +00001359 }
Chris Lattner24943d22010-06-08 16:52:24 +00001360 return error;
1361}
1362
Greg Clayton4fb400f2010-09-27 21:07:38 +00001363Error
Greg Clayton72e1c782011-01-22 23:43:18 +00001364ProcessGDBRemote::WillDetach ()
1365{
Greg Clayton2860ba92011-01-23 19:58:49 +00001366 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
1367 if (log)
1368 log->Printf ("ProcessGDBRemote::WillDetach()");
1369
Greg Clayton72e1c782011-01-22 23:43:18 +00001370 bool discard_thread_plans = true;
1371 bool catch_stop_event = true;
Greg Clayton72e1c782011-01-22 23:43:18 +00001372 EventSP event_sp;
Greg Clayton68ca8232011-01-25 02:58:48 +00001373 return InterruptIfRunning (discard_thread_plans, catch_stop_event, event_sp);
Greg Clayton72e1c782011-01-22 23:43:18 +00001374}
1375
1376Error
Greg Clayton4fb400f2010-09-27 21:07:38 +00001377ProcessGDBRemote::DoDetach()
1378{
1379 Error error;
Greg Claytone005f2c2010-11-06 01:53:30 +00001380 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Greg Clayton4fb400f2010-09-27 21:07:38 +00001381 if (log)
1382 log->Printf ("ProcessGDBRemote::DoDetach()");
1383
1384 DisableAllBreakpointSites ();
1385
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001386 m_thread_list.DiscardThreadPlans();
Greg Clayton4fb400f2010-09-27 21:07:38 +00001387
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001388 size_t response_size = m_gdb_comm.SendPacket ("D", 1);
1389 if (log)
Greg Clayton4fb400f2010-09-27 21:07:38 +00001390 {
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001391 if (response_size)
1392 log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
1393 else
1394 log->PutCString ("ProcessGDBRemote::DoDetach() detach packet send failed");
Greg Clayton4fb400f2010-09-27 21:07:38 +00001395 }
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001396 // Sleep for one second to let the process get all detached...
Greg Clayton4fb400f2010-09-27 21:07:38 +00001397 StopAsyncThread ();
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001398
Greg Clayton4fb400f2010-09-27 21:07:38 +00001399 m_gdb_comm.StopReadThread();
Greg Clayton4fb400f2010-09-27 21:07:38 +00001400 m_gdb_comm.Disconnect(); // Disconnect from the debug server.
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001401
1402 SetPrivateState (eStateDetached);
1403 ResumePrivateStateThread();
1404
1405 //KillDebugserverProcess ();
Greg Clayton4fb400f2010-09-27 21:07:38 +00001406 return error;
1407}
Chris Lattner24943d22010-06-08 16:52:24 +00001408
1409Error
1410ProcessGDBRemote::DoDestroy ()
1411{
1412 Error error;
Greg Claytone005f2c2010-11-06 01:53:30 +00001413 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00001414 if (log)
1415 log->Printf ("ProcessGDBRemote::DoDestroy()");
1416
1417 // Interrupt if our inferior is running...
Greg Claytona4881d02011-01-22 07:12:45 +00001418 if (m_gdb_comm.IsConnected())
Chris Lattner24943d22010-06-08 16:52:24 +00001419 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001420 if (m_public_state.GetValue() == eStateAttaching)
Greg Clayton27a8dd72011-01-25 04:57:42 +00001421 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001422 // We are being asked to halt during an attach. We need to just close
1423 // our file handle and debugserver will go away, and we can be done...
1424 m_gdb_comm.Disconnect();
Greg Clayton27a8dd72011-01-25 04:57:42 +00001425 }
1426 else
Greg Clayton72e1c782011-01-22 23:43:18 +00001427 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001428
1429 StringExtractorGDBRemote response;
1430 bool send_async = true;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001431 if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async))
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001432 {
1433 char packet_cmd = response.GetChar(0);
1434
1435 if (packet_cmd == 'W' || packet_cmd == 'X')
1436 {
1437 m_last_stop_packet = response;
1438 SetExitStatus(response.GetHexU8(), NULL);
1439 }
1440 }
1441 else
1442 {
1443 SetExitStatus(SIGABRT, NULL);
1444 //error.SetErrorString("kill packet failed");
1445 }
Greg Clayton72e1c782011-01-22 23:43:18 +00001446 }
1447 }
Chris Lattner24943d22010-06-08 16:52:24 +00001448 StopAsyncThread ();
1449 m_gdb_comm.StopReadThread();
1450 KillDebugserverProcess ();
Johnny Chenc5b15db2010-09-03 22:35:47 +00001451 m_gdb_comm.Disconnect(); // Disconnect from the debug server.
Chris Lattner24943d22010-06-08 16:52:24 +00001452 return error;
1453}
1454
Chris Lattner24943d22010-06-08 16:52:24 +00001455//------------------------------------------------------------------
1456// Process Queries
1457//------------------------------------------------------------------
1458
1459bool
1460ProcessGDBRemote::IsAlive ()
1461{
Greg Clayton58e844b2010-12-08 05:08:21 +00001462 return m_gdb_comm.IsConnected() && m_private_state.GetValue() != eStateExited;
Chris Lattner24943d22010-06-08 16:52:24 +00001463}
1464
1465addr_t
1466ProcessGDBRemote::GetImageInfoAddress()
1467{
1468 if (!m_gdb_comm.IsRunning())
1469 {
1470 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001471 if (m_gdb_comm.SendPacketAndWaitForResponse("qShlibInfoAddr", ::strlen ("qShlibInfoAddr"), response, false))
Chris Lattner24943d22010-06-08 16:52:24 +00001472 {
Greg Clayton61d043b2011-03-22 04:00:09 +00001473 if (response.IsNormalResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001474 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
1475 }
1476 }
1477 return LLDB_INVALID_ADDRESS;
1478}
1479
Chris Lattner24943d22010-06-08 16:52:24 +00001480//------------------------------------------------------------------
1481// Process Memory
1482//------------------------------------------------------------------
1483size_t
1484ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
1485{
1486 if (size > m_max_memory_size)
1487 {
1488 // Keep memory read sizes down to a sane limit. This function will be
1489 // called multiple times in order to complete the task by
1490 // lldb_private::Process so it is ok to do this.
1491 size = m_max_memory_size;
1492 }
1493
1494 char packet[64];
1495 const int packet_len = ::snprintf (packet, sizeof(packet), "m%llx,%zx", (uint64_t)addr, size);
1496 assert (packet_len + 1 < sizeof(packet));
1497 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001498 if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
Chris Lattner24943d22010-06-08 16:52:24 +00001499 {
Greg Clayton61d043b2011-03-22 04:00:09 +00001500 if (response.IsNormalResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001501 {
1502 error.Clear();
1503 return response.GetHexBytes(buf, size, '\xdd');
1504 }
Greg Clayton61d043b2011-03-22 04:00:09 +00001505 else if (response.IsErrorResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001506 error.SetErrorStringWithFormat("gdb remote returned an error: %s", response.GetStringRef().c_str());
Greg Clayton61d043b2011-03-22 04:00:09 +00001507 else if (response.IsUnsupportedResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001508 error.SetErrorStringWithFormat("'%s' packet unsupported", packet);
1509 else
1510 error.SetErrorStringWithFormat("unexpected response to '%s': '%s'", packet, response.GetStringRef().c_str());
1511 }
1512 else
1513 {
1514 error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet);
1515 }
1516 return 0;
1517}
1518
1519size_t
1520ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
1521{
1522 StreamString packet;
1523 packet.Printf("M%llx,%zx:", addr, size);
Greg Claytoncd548032011-02-01 01:31:41 +00001524 packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +00001525 StringExtractorGDBRemote response;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001526 if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true))
Chris Lattner24943d22010-06-08 16:52:24 +00001527 {
Greg Clayton61d043b2011-03-22 04:00:09 +00001528 if (response.IsOKResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001529 {
1530 error.Clear();
1531 return size;
1532 }
Greg Clayton61d043b2011-03-22 04:00:09 +00001533 else if (response.IsErrorResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001534 error.SetErrorStringWithFormat("gdb remote returned an error: %s", response.GetStringRef().c_str());
Greg Clayton61d043b2011-03-22 04:00:09 +00001535 else if (response.IsUnsupportedResponse())
Chris Lattner24943d22010-06-08 16:52:24 +00001536 error.SetErrorStringWithFormat("'%s' packet unsupported", packet.GetString().c_str());
1537 else
1538 error.SetErrorStringWithFormat("unexpected response to '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str());
1539 }
1540 else
1541 {
1542 error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet.GetString().c_str());
1543 }
1544 return 0;
1545}
1546
1547lldb::addr_t
1548ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
1549{
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001550 addr_t allocated_addr = m_gdb_comm.AllocateMemory (size, permissions);
Chris Lattner24943d22010-06-08 16:52:24 +00001551 if (allocated_addr == LLDB_INVALID_ADDRESS)
1552 error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %u", size, permissions);
1553 else
1554 error.Clear();
1555 return allocated_addr;
1556}
1557
1558Error
1559ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
1560{
1561 Error error;
Greg Claytonc97bfdb2011-03-10 02:26:48 +00001562 if (!m_gdb_comm.DeallocateMemory (addr))
Chris Lattner24943d22010-06-08 16:52:24 +00001563 error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
1564 return error;
1565}
1566
1567
1568//------------------------------------------------------------------
1569// Process STDIO
1570//------------------------------------------------------------------
1571
1572size_t
1573ProcessGDBRemote::GetSTDOUT (char *buf, size_t buf_size, Error &error)
1574{
1575 Mutex::Locker locker(m_stdio_mutex);
1576 size_t bytes_available = m_stdout_data.size();
1577 if (bytes_available > 0)
1578 {
Greg Clayton0bfda0b2011-02-05 02:25:06 +00001579 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
1580 if (log)
1581 log->Printf ("ProcessGDBRemote::%s (&%p[%u]) ...", __FUNCTION__, buf, buf_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001582 if (bytes_available > buf_size)
1583 {
Greg Clayton53d68e72010-07-20 22:52:08 +00001584 memcpy(buf, m_stdout_data.c_str(), buf_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001585 m_stdout_data.erase(0, buf_size);
1586 bytes_available = buf_size;
1587 }
1588 else
1589 {
Greg Clayton53d68e72010-07-20 22:52:08 +00001590 memcpy(buf, m_stdout_data.c_str(), bytes_available);
Chris Lattner24943d22010-06-08 16:52:24 +00001591 m_stdout_data.clear();
1592
1593 //ResetEventBits(eBroadcastBitSTDOUT);
1594 }
1595 }
1596 return bytes_available;
1597}
1598
1599size_t
1600ProcessGDBRemote::GetSTDERR (char *buf, size_t buf_size, Error &error)
1601{
1602 // Can we get STDERR through the remote protocol?
1603 return 0;
1604}
1605
1606size_t
1607ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error)
1608{
1609 if (m_stdio_communication.IsConnected())
1610 {
1611 ConnectionStatus status;
1612 m_stdio_communication.Write(src, src_len, status, NULL);
1613 }
1614 return 0;
1615}
1616
1617Error
1618ProcessGDBRemote::EnableBreakpoint (BreakpointSite *bp_site)
1619{
1620 Error error;
1621 assert (bp_site != NULL);
1622
Greg Claytone005f2c2010-11-06 01:53:30 +00001623 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +00001624 user_id_t site_id = bp_site->GetID();
1625 const addr_t addr = bp_site->GetLoadAddress();
1626 if (log)
1627 log->Printf ("ProcessGDBRemote::EnableBreakpoint (size_id = %d) address = 0x%llx", site_id, (uint64_t)addr);
1628
1629 if (bp_site->IsEnabled())
1630 {
1631 if (log)
1632 log->Printf ("ProcessGDBRemote::EnableBreakpoint (size_id = %d) address = 0x%llx -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
1633 return error;
1634 }
1635 else
1636 {
1637 const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
1638
1639 if (bp_site->HardwarePreferred())
1640 {
1641 // Try and set hardware breakpoint, and if that fails, fall through
1642 // and set a software breakpoint?
Greg Claytonb72d0f02011-04-12 05:54:46 +00001643 if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointHardware))
Chris Lattner24943d22010-06-08 16:52:24 +00001644 {
Greg Claytonb72d0f02011-04-12 05:54:46 +00001645 if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001646 {
1647 bp_site->SetEnabled(true);
Greg Claytonb72d0f02011-04-12 05:54:46 +00001648 bp_site->SetType (BreakpointSite::eHardware);
Chris Lattner24943d22010-06-08 16:52:24 +00001649 return error;
1650 }
Chris Lattner24943d22010-06-08 16:52:24 +00001651 }
1652 }
Greg Claytonb72d0f02011-04-12 05:54:46 +00001653
1654 if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
Chris Lattner24943d22010-06-08 16:52:24 +00001655 {
Greg Claytonb72d0f02011-04-12 05:54:46 +00001656 if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
1657 {
1658 bp_site->SetEnabled(true);
1659 bp_site->SetType (BreakpointSite::eExternal);
1660 return error;
1661 }
Chris Lattner24943d22010-06-08 16:52:24 +00001662 }
Greg Claytonb72d0f02011-04-12 05:54:46 +00001663
1664 return EnableSoftwareBreakpoint (bp_site);
Chris Lattner24943d22010-06-08 16:52:24 +00001665 }
1666
1667 if (log)
1668 {
1669 const char *err_string = error.AsCString();
1670 log->Printf ("ProcessGDBRemote::EnableBreakpoint() error for breakpoint at 0x%8.8llx: %s",
1671 bp_site->GetLoadAddress(),
1672 err_string ? err_string : "NULL");
1673 }
1674 // We shouldn't reach here on a successful breakpoint enable...
1675 if (error.Success())
1676 error.SetErrorToGenericError();
1677 return error;
1678}
1679
1680Error
1681ProcessGDBRemote::DisableBreakpoint (BreakpointSite *bp_site)
1682{
1683 Error error;
1684 assert (bp_site != NULL);
1685 addr_t addr = bp_site->GetLoadAddress();
1686 user_id_t site_id = bp_site->GetID();
Greg Claytone005f2c2010-11-06 01:53:30 +00001687 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +00001688 if (log)
1689 log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx", site_id, (uint64_t)addr);
1690
1691 if (bp_site->IsEnabled())
1692 {
1693 const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
1694
Greg Claytonb72d0f02011-04-12 05:54:46 +00001695 BreakpointSite::Type bp_type = bp_site->GetType();
1696 switch (bp_type)
Chris Lattner24943d22010-06-08 16:52:24 +00001697 {
Greg Claytonb72d0f02011-04-12 05:54:46 +00001698 case BreakpointSite::eSoftware:
1699 error = DisableSoftwareBreakpoint (bp_site);
1700 break;
1701
1702 case BreakpointSite::eHardware:
1703 if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
1704 error.SetErrorToGenericError();
1705 break;
1706
1707 case BreakpointSite::eExternal:
1708 if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
1709 error.SetErrorToGenericError();
1710 break;
Chris Lattner24943d22010-06-08 16:52:24 +00001711 }
Greg Claytonb72d0f02011-04-12 05:54:46 +00001712 if (error.Success())
1713 bp_site->SetEnabled(false);
Chris Lattner24943d22010-06-08 16:52:24 +00001714 }
1715 else
1716 {
1717 if (log)
1718 log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS (already disabled)", site_id, (uint64_t)addr);
1719 return error;
1720 }
1721
1722 if (error.Success())
1723 error.SetErrorToGenericError();
1724 return error;
1725}
1726
1727Error
1728ProcessGDBRemote::EnableWatchpoint (WatchpointLocation *wp)
1729{
1730 Error error;
1731 if (wp)
1732 {
1733 user_id_t watchID = wp->GetID();
1734 addr_t addr = wp->GetLoadAddress();
Greg Claytone005f2c2010-11-06 01:53:30 +00001735 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +00001736 if (log)
1737 log->Printf ("ProcessGDBRemote::EnableWatchpoint(watchID = %d)", watchID);
1738 if (wp->IsEnabled())
1739 {
1740 if (log)
1741 log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %d) addr = 0x%8.8llx: watchpoint already enabled.", watchID, (uint64_t)addr);
1742 return error;
1743 }
1744 else
1745 {
1746 // Pass down an appropriate z/Z packet...
1747 error.SetErrorString("watchpoints not supported");
1748 }
1749 }
1750 else
1751 {
1752 error.SetErrorString("Watchpoint location argument was NULL.");
1753 }
1754 if (error.Success())
1755 error.SetErrorToGenericError();
1756 return error;
1757}
1758
1759Error
1760ProcessGDBRemote::DisableWatchpoint (WatchpointLocation *wp)
1761{
1762 Error error;
1763 if (wp)
1764 {
1765 user_id_t watchID = wp->GetID();
1766
Greg Claytone005f2c2010-11-06 01:53:30 +00001767 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +00001768
1769 addr_t addr = wp->GetLoadAddress();
1770 if (log)
1771 log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %d) addr = 0x%8.8llx", watchID, (uint64_t)addr);
1772
1773 if (wp->IsHardware())
1774 {
1775 // Pass down an appropriate z/Z packet...
1776 error.SetErrorString("watchpoints not supported");
1777 }
1778 // TODO: clear software watchpoints if we implement them
1779 }
1780 else
1781 {
1782 error.SetErrorString("Watchpoint location argument was NULL.");
1783 }
1784 if (error.Success())
1785 error.SetErrorToGenericError();
1786 return error;
1787}
1788
1789void
1790ProcessGDBRemote::Clear()
1791{
1792 m_flags = 0;
1793 m_thread_list.Clear();
1794 {
1795 Mutex::Locker locker(m_stdio_mutex);
1796 m_stdout_data.clear();
1797 }
Chris Lattner24943d22010-06-08 16:52:24 +00001798}
1799
1800Error
1801ProcessGDBRemote::DoSignal (int signo)
1802{
1803 Error error;
Greg Claytone005f2c2010-11-06 01:53:30 +00001804 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00001805 if (log)
1806 log->Printf ("ProcessGDBRemote::DoSignal (signal = %d)", signo);
1807
1808 if (!m_gdb_comm.SendAsyncSignal (signo))
1809 error.SetErrorStringWithFormat("failed to send signal %i", signo);
1810 return error;
1811}
1812
Chris Lattner24943d22010-06-08 16:52:24 +00001813Error
Greg Claytonb72d0f02011-04-12 05:54:46 +00001814ProcessGDBRemote::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 +00001815{
1816 Error error;
1817 if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
1818 {
1819 // If we locate debugserver, keep that located version around
1820 static FileSpec g_debugserver_file_spec;
1821
Greg Claytonb72d0f02011-04-12 05:54:46 +00001822 ProcessLaunchInfo launch_info;
Chris Lattner24943d22010-06-08 16:52:24 +00001823 char debugserver_path[PATH_MAX];
Greg Claytonb72d0f02011-04-12 05:54:46 +00001824 FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
Chris Lattner24943d22010-06-08 16:52:24 +00001825
1826 // Always check to see if we have an environment override for the path
1827 // to the debugserver to use and use it if we do.
1828 const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
1829 if (env_debugserver_path)
Greg Clayton537a7a82010-10-20 20:54:39 +00001830 debugserver_file_spec.SetFile (env_debugserver_path, false);
Chris Lattner24943d22010-06-08 16:52:24 +00001831 else
1832 debugserver_file_spec = g_debugserver_file_spec;
1833 bool debugserver_exists = debugserver_file_spec.Exists();
1834 if (!debugserver_exists)
1835 {
1836 // The debugserver binary is in the LLDB.framework/Resources
1837 // directory.
Greg Clayton24b48ff2010-10-17 22:03:32 +00001838 if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
Chris Lattner24943d22010-06-08 16:52:24 +00001839 {
Greg Clayton24b48ff2010-10-17 22:03:32 +00001840 debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
Chris Lattner24943d22010-06-08 16:52:24 +00001841 debugserver_exists = debugserver_file_spec.Exists();
Greg Clayton24b48ff2010-10-17 22:03:32 +00001842 if (debugserver_exists)
1843 {
1844 g_debugserver_file_spec = debugserver_file_spec;
1845 }
1846 else
1847 {
1848 g_debugserver_file_spec.Clear();
1849 debugserver_file_spec.Clear();
1850 }
Chris Lattner24943d22010-06-08 16:52:24 +00001851 }
1852 }
1853
1854 if (debugserver_exists)
1855 {
1856 debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
1857
1858 m_stdio_communication.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +00001859
Greg Claytone005f2c2010-11-06 01:53:30 +00001860 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00001861
Greg Claytonb72d0f02011-04-12 05:54:46 +00001862 Args &debugserver_args = launch_info.GetArguments();
Chris Lattner24943d22010-06-08 16:52:24 +00001863 char arg_cstr[PATH_MAX];
Chris Lattner24943d22010-06-08 16:52:24 +00001864
Chris Lattner24943d22010-06-08 16:52:24 +00001865 // Start args with "debugserver /file/path -r --"
1866 debugserver_args.AppendArgument(debugserver_path);
1867 debugserver_args.AppendArgument(debugserver_url);
Greg Clayton24b48ff2010-10-17 22:03:32 +00001868 // use native registers, not the GDB registers
1869 debugserver_args.AppendArgument("--native-regs");
1870 // make debugserver run in its own session so signals generated by
1871 // special terminal key sequences (^C) don't affect debugserver
1872 debugserver_args.AppendArgument("--setsid");
Chris Lattner24943d22010-06-08 16:52:24 +00001873
Chris Lattner24943d22010-06-08 16:52:24 +00001874 const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
1875 if (env_debugserver_log_file)
1876 {
1877 ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
1878 debugserver_args.AppendArgument(arg_cstr);
1879 }
1880
1881 const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
1882 if (env_debugserver_log_flags)
1883 {
1884 ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
1885 debugserver_args.AppendArgument(arg_cstr);
1886 }
Greg Claytoncc3e6402011-01-25 06:55:13 +00001887// debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
Greg Clayton7e2f91c2011-01-29 07:10:55 +00001888// debugserver_args.AppendArgument("--log-flags=0x802e0e");
Chris Lattner24943d22010-06-08 16:52:24 +00001889
Greg Claytonb72d0f02011-04-12 05:54:46 +00001890 // We currently send down all arguments, attach pids, or attach
1891 // process names in dedicated GDB server packets, so we don't need
1892 // to pass them as arguments. This is currently because of all the
1893 // things we need to setup prior to launching: the environment,
1894 // current working dir, file actions, etc.
1895#if 0
Chris Lattner24943d22010-06-08 16:52:24 +00001896 // Now append the program arguments
Greg Claytona2f74232011-02-24 22:24:29 +00001897 if (inferior_argv)
Chris Lattner24943d22010-06-08 16:52:24 +00001898 {
Greg Claytona2f74232011-02-24 22:24:29 +00001899 // Terminate the debugserver args so we can now append the inferior args
1900 debugserver_args.AppendArgument("--");
Chris Lattner24943d22010-06-08 16:52:24 +00001901
Greg Claytona2f74232011-02-24 22:24:29 +00001902 for (int i = 0; inferior_argv[i] != NULL; ++i)
1903 debugserver_args.AppendArgument (inferior_argv[i]);
Chris Lattner24943d22010-06-08 16:52:24 +00001904 }
1905 else if (attach_pid != LLDB_INVALID_PROCESS_ID)
1906 {
1907 ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
1908 debugserver_args.AppendArgument (arg_cstr);
1909 }
1910 else if (attach_name && attach_name[0])
1911 {
1912 if (wait_for_launch)
1913 debugserver_args.AppendArgument ("--waitfor");
1914 else
1915 debugserver_args.AppendArgument ("--attach");
1916 debugserver_args.AppendArgument (attach_name);
1917 }
Chris Lattner24943d22010-06-08 16:52:24 +00001918#endif
Greg Claytonb72d0f02011-04-12 05:54:46 +00001919
1920 ProcessLaunchInfo::FileAction file_action;
1921
1922 // Close STDIN, STDOUT and STDERR. We might need to redirect them
1923 // to "/dev/null" if we run into any problems.
1924 file_action.Close (STDIN_FILENO);
1925 launch_info.AppendFileAction (file_action);
1926 file_action.Close (STDOUT_FILENO);
1927 launch_info.AppendFileAction (file_action);
1928 file_action.Close (STDERR_FILENO);
1929 launch_info.AppendFileAction (file_action);
Chris Lattner24943d22010-06-08 16:52:24 +00001930
1931 if (log)
1932 {
1933 StreamString strm;
1934 debugserver_args.Dump (&strm);
1935 log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData());
1936 }
1937
Greg Claytonb72d0f02011-04-12 05:54:46 +00001938 error = Host::LaunchProcess(launch_info);
Greg Claytone9d0df42010-07-02 01:29:13 +00001939
Greg Claytonb72d0f02011-04-12 05:54:46 +00001940 if (error.Success ())
1941 m_debugserver_pid = launch_info.GetProcessID();
1942 else
Chris Lattner24943d22010-06-08 16:52:24 +00001943 m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
1944
1945 if (error.Fail() || log)
Greg Claytonb72d0f02011-04-12 05:54:46 +00001946 error.PutToLog(log.get(), "Host::LaunchProcess (launch_info) => pid=%i, path='%s'", m_debugserver_pid, debugserver_path);
Chris Lattner24943d22010-06-08 16:52:24 +00001947 }
1948 else
1949 {
1950 error.SetErrorStringWithFormat ("Unable to locate " DEBUGSERVER_BASENAME ".\n");
1951 }
1952
1953 if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
1954 StartAsyncThread ();
1955 }
1956 return error;
1957}
1958
1959bool
1960ProcessGDBRemote::MonitorDebugserverProcess
1961(
1962 void *callback_baton,
1963 lldb::pid_t debugserver_pid,
1964 int signo, // Zero for no signal
1965 int exit_status // Exit value of process if signal is zero
1966)
1967{
1968 // We pass in the ProcessGDBRemote inferior process it and name it
1969 // "gdb_remote_pid". The process ID is passed in the "callback_baton"
1970 // pointer value itself, thus we need the double cast...
1971
1972 // "debugserver_pid" argument passed in is the process ID for
1973 // debugserver that we are tracking...
1974
Greg Clayton75ccf502010-08-21 02:22:51 +00001975 ProcessGDBRemote *process = (ProcessGDBRemote *)callback_baton;
Greg Clayton72e1c782011-01-22 23:43:18 +00001976
1977 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
1978 if (log)
1979 log->Printf ("ProcessGDBRemote::MonitorDebugserverProcess (baton=%p, pid=%i, signo=%i (0x%x), exit_status=%i)", callback_baton, debugserver_pid, signo, signo, exit_status);
1980
Greg Clayton75ccf502010-08-21 02:22:51 +00001981 if (process)
Chris Lattner24943d22010-06-08 16:52:24 +00001982 {
Greg Clayton75ccf502010-08-21 02:22:51 +00001983 // Sleep for a half a second to make sure our inferior process has
1984 // time to set its exit status before we set it incorrectly when
1985 // both the debugserver and the inferior process shut down.
1986 usleep (500000);
1987 // If our process hasn't yet exited, debugserver might have died.
1988 // If the process did exit, the we are reaping it.
Greg Clayton3b2c41c2010-10-18 04:14:23 +00001989 const StateType state = process->GetState();
1990
1991 if (process->m_debugserver_pid != LLDB_INVALID_PROCESS_ID &&
1992 state != eStateInvalid &&
1993 state != eStateUnloaded &&
1994 state != eStateExited &&
1995 state != eStateDetached)
Chris Lattner24943d22010-06-08 16:52:24 +00001996 {
Greg Clayton75ccf502010-08-21 02:22:51 +00001997 char error_str[1024];
1998 if (signo)
Chris Lattner24943d22010-06-08 16:52:24 +00001999 {
Greg Clayton75ccf502010-08-21 02:22:51 +00002000 const char *signal_cstr = process->GetUnixSignals().GetSignalAsCString (signo);
2001 if (signal_cstr)
2002 ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
Chris Lattner24943d22010-06-08 16:52:24 +00002003 else
Greg Clayton75ccf502010-08-21 02:22:51 +00002004 ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %i", signo);
Chris Lattner24943d22010-06-08 16:52:24 +00002005 }
2006 else
2007 {
Greg Clayton75ccf502010-08-21 02:22:51 +00002008 ::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 +00002009 }
Greg Clayton75ccf502010-08-21 02:22:51 +00002010
2011 process->SetExitStatus (-1, error_str);
2012 }
Greg Clayton3b2c41c2010-10-18 04:14:23 +00002013 // Debugserver has exited we need to let our ProcessGDBRemote
2014 // know that it no longer has a debugserver instance
2015 process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
2016 // We are returning true to this function below, so we can
2017 // forget about the monitor handle.
2018 process->m_debugserver_thread = LLDB_INVALID_HOST_THREAD;
Chris Lattner24943d22010-06-08 16:52:24 +00002019 }
2020 return true;
2021}
2022
2023void
2024ProcessGDBRemote::KillDebugserverProcess ()
2025{
2026 if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
2027 {
2028 ::kill (m_debugserver_pid, SIGINT);
2029 m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
2030 }
2031}
2032
2033void
2034ProcessGDBRemote::Initialize()
2035{
2036 static bool g_initialized = false;
2037
2038 if (g_initialized == false)
2039 {
2040 g_initialized = true;
2041 PluginManager::RegisterPlugin (GetPluginNameStatic(),
2042 GetPluginDescriptionStatic(),
2043 CreateInstance);
2044
2045 Log::Callbacks log_callbacks = {
2046 ProcessGDBRemoteLog::DisableLog,
2047 ProcessGDBRemoteLog::EnableLog,
2048 ProcessGDBRemoteLog::ListLogCategories
2049 };
2050
2051 Log::RegisterLogChannel (ProcessGDBRemote::GetPluginNameStatic(), log_callbacks);
2052 }
2053}
2054
2055bool
Chris Lattner24943d22010-06-08 16:52:24 +00002056ProcessGDBRemote::StartAsyncThread ()
2057{
Greg Claytone005f2c2010-11-06 01:53:30 +00002058 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00002059
2060 if (log)
2061 log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
2062
2063 // Create a thread that watches our internal state and controls which
2064 // events make it to clients (into the DCProcess event queue).
2065 m_async_thread = Host::ThreadCreate ("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
Greg Clayton09c81ef2011-02-08 01:34:25 +00002066 return IS_VALID_LLDB_HOST_THREAD(m_async_thread);
Chris Lattner24943d22010-06-08 16:52:24 +00002067}
2068
2069void
2070ProcessGDBRemote::StopAsyncThread ()
2071{
Greg Claytone005f2c2010-11-06 01:53:30 +00002072 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00002073
2074 if (log)
2075 log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
2076
2077 m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
2078
2079 // Stop the stdio thread
Greg Clayton09c81ef2011-02-08 01:34:25 +00002080 if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
Chris Lattner24943d22010-06-08 16:52:24 +00002081 {
2082 Host::ThreadJoin (m_async_thread, NULL, NULL);
2083 }
2084}
2085
2086
2087void *
2088ProcessGDBRemote::AsyncThread (void *arg)
2089{
2090 ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
2091
Greg Claytone005f2c2010-11-06 01:53:30 +00002092 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +00002093 if (log)
2094 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
2095
2096 Listener listener ("ProcessGDBRemote::AsyncThread");
2097 EventSP event_sp;
2098 const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
2099 eBroadcastBitAsyncThreadShouldExit;
2100
2101 if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
2102 {
Greg Claytona2f74232011-02-24 22:24:29 +00002103 listener.StartListeningForEvents (&process->m_gdb_comm, Communication::eBroadcastBitReadThreadDidExit);
2104
Chris Lattner24943d22010-06-08 16:52:24 +00002105 bool done = false;
2106 while (!done)
2107 {
2108 if (log)
2109 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
2110 if (listener.WaitForEvent (NULL, event_sp))
2111 {
2112 const uint32_t event_type = event_sp->GetType();
Greg Claytona2f74232011-02-24 22:24:29 +00002113 if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
Chris Lattner24943d22010-06-08 16:52:24 +00002114 {
Greg Claytona2f74232011-02-24 22:24:29 +00002115 if (log)
2116 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 +00002117
Greg Claytona2f74232011-02-24 22:24:29 +00002118 switch (event_type)
2119 {
2120 case eBroadcastBitAsyncContinue:
Chris Lattner24943d22010-06-08 16:52:24 +00002121 {
Greg Claytona2f74232011-02-24 22:24:29 +00002122 const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
Chris Lattner24943d22010-06-08 16:52:24 +00002123
Greg Claytona2f74232011-02-24 22:24:29 +00002124 if (continue_packet)
Chris Lattner24943d22010-06-08 16:52:24 +00002125 {
Greg Claytona2f74232011-02-24 22:24:29 +00002126 const char *continue_cstr = (const char *)continue_packet->GetBytes ();
2127 const size_t continue_cstr_len = continue_packet->GetByteSize ();
2128 if (log)
2129 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
Chris Lattner24943d22010-06-08 16:52:24 +00002130
Greg Claytona2f74232011-02-24 22:24:29 +00002131 if (::strstr (continue_cstr, "vAttach") == NULL)
2132 process->SetPrivateState(eStateRunning);
2133 StringExtractorGDBRemote response;
2134 StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
Chris Lattner24943d22010-06-08 16:52:24 +00002135
Greg Claytona2f74232011-02-24 22:24:29 +00002136 switch (stop_state)
2137 {
2138 case eStateStopped:
2139 case eStateCrashed:
2140 case eStateSuspended:
2141 process->m_last_stop_packet = response;
2142 process->m_last_stop_packet.SetFilePos (0);
2143 process->SetPrivateState (stop_state);
2144 break;
Chris Lattner24943d22010-06-08 16:52:24 +00002145
Greg Claytona2f74232011-02-24 22:24:29 +00002146 case eStateExited:
2147 process->m_last_stop_packet = response;
2148 process->m_last_stop_packet.SetFilePos (0);
2149 response.SetFilePos(1);
2150 process->SetExitStatus(response.GetHexU8(), NULL);
2151 done = true;
2152 break;
2153
2154 case eStateInvalid:
2155 process->SetExitStatus(-1, "lost connection");
2156 break;
2157
2158 default:
2159 process->SetPrivateState (stop_state);
2160 break;
2161 }
Chris Lattner24943d22010-06-08 16:52:24 +00002162 }
2163 }
Greg Claytona2f74232011-02-24 22:24:29 +00002164 break;
Chris Lattner24943d22010-06-08 16:52:24 +00002165
Greg Claytona2f74232011-02-24 22:24:29 +00002166 case eBroadcastBitAsyncThreadShouldExit:
2167 if (log)
2168 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
2169 done = true;
2170 break;
Chris Lattner24943d22010-06-08 16:52:24 +00002171
Greg Claytona2f74232011-02-24 22:24:29 +00002172 default:
2173 if (log)
2174 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
2175 done = true;
2176 break;
2177 }
2178 }
2179 else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
2180 {
2181 if (event_type & Communication::eBroadcastBitReadThreadDidExit)
2182 {
2183 process->SetExitStatus (-1, "lost connection");
Chris Lattner24943d22010-06-08 16:52:24 +00002184 done = true;
Greg Claytona2f74232011-02-24 22:24:29 +00002185 }
Chris Lattner24943d22010-06-08 16:52:24 +00002186 }
2187 }
2188 else
2189 {
2190 if (log)
2191 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
2192 done = true;
2193 }
2194 }
2195 }
2196
2197 if (log)
2198 log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
2199
2200 process->m_async_thread = LLDB_INVALID_HOST_THREAD;
2201 return NULL;
2202}
2203
Chris Lattner24943d22010-06-08 16:52:24 +00002204const char *
2205ProcessGDBRemote::GetDispatchQueueNameForThread
2206(
2207 addr_t thread_dispatch_qaddr,
2208 std::string &dispatch_queue_name
2209)
2210{
2211 dispatch_queue_name.clear();
2212 if (thread_dispatch_qaddr != 0 && thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
2213 {
2214 // Cache the dispatch_queue_offsets_addr value so we don't always have
2215 // to look it up
2216 if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
2217 {
Greg Claytonaf6e9e42010-10-12 17:33:06 +00002218 static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
2219 const Symbol *dispatch_queue_offsets_symbol = NULL;
Greg Clayton24bc5d92011-03-30 18:16:51 +00002220 ModuleSP module_sp(GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.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
2224 if (dispatch_queue_offsets_symbol == NULL)
2225 {
Greg Clayton24bc5d92011-03-30 18:16:51 +00002226 module_sp = GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libdispatch.dylib", false), NULL, NULL);
Greg Claytonaf6e9e42010-10-12 17:33:06 +00002227 if (module_sp)
2228 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
2229 }
Chris Lattner24943d22010-06-08 16:52:24 +00002230 if (dispatch_queue_offsets_symbol)
Greg Claytoneea26402010-09-14 23:36:40 +00002231 m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetValue().GetLoadAddress(&m_target);
Chris Lattner24943d22010-06-08 16:52:24 +00002232
2233 if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
2234 return NULL;
2235 }
2236
2237 uint8_t memory_buffer[8];
Greg Clayton395fc332011-02-15 21:59:32 +00002238 DataExtractor data (memory_buffer,
2239 sizeof(memory_buffer),
2240 m_target.GetArchitecture().GetByteOrder(),
2241 m_target.GetArchitecture().GetAddressByteSize());
Chris Lattner24943d22010-06-08 16:52:24 +00002242
2243 // Excerpt from src/queue_private.h
2244 struct dispatch_queue_offsets_s
2245 {
2246 uint16_t dqo_version;
2247 uint16_t dqo_label;
2248 uint16_t dqo_label_size;
2249 } dispatch_queue_offsets;
2250
2251
2252 Error error;
2253 if (ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
2254 {
2255 uint32_t data_offset = 0;
2256 if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
2257 {
2258 if (ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
2259 {
2260 data_offset = 0;
2261 lldb::addr_t queue_addr = data.GetAddress(&data_offset);
2262 lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
2263 dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0');
2264 size_t bytes_read = ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error);
2265 if (bytes_read < dispatch_queue_offsets.dqo_label_size)
2266 dispatch_queue_name.erase (bytes_read);
2267 }
2268 }
2269 }
2270 }
2271 if (dispatch_queue_name.empty())
2272 return NULL;
2273 return dispatch_queue_name.c_str();
2274}
2275
Greg Claytone4b9c1f2011-03-08 22:40:15 +00002276//uint32_t
2277//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
2278//{
2279// // If we are planning to launch the debugserver remotely, then we need to fire up a debugserver
2280// // process and ask it for the list of processes. But if we are local, we can let the Host do it.
2281// if (m_local_debugserver)
2282// {
2283// return Host::ListProcessesMatchingName (name, matches, pids);
2284// }
2285// else
2286// {
2287// // FIXME: Implement talking to the remote debugserver.
2288// return 0;
2289// }
2290//
2291//}
2292//
Jim Ingham55e01d82011-01-22 01:33:44 +00002293bool
2294ProcessGDBRemote::NewThreadNotifyBreakpointHit (void *baton,
2295 lldb_private::StoppointCallbackContext *context,
2296 lldb::user_id_t break_id,
2297 lldb::user_id_t break_loc_id)
2298{
2299 // I don't think I have to do anything here, just make sure I notice the new thread when it starts to
2300 // run so I can stop it if that's what I want to do.
2301 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
2302 if (log)
2303 log->Printf("Hit New Thread Notification breakpoint.");
2304 return false;
2305}
2306
2307
2308bool
2309ProcessGDBRemote::StartNoticingNewThreads()
2310{
2311 static const char *bp_names[] =
2312 {
2313 "start_wqthread",
Jim Inghamff276fe2011-02-08 05:19:01 +00002314 "_pthread_wqthread",
Jim Ingham55e01d82011-01-22 01:33:44 +00002315 "_pthread_start",
2316 NULL
2317 };
2318
2319 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
2320 size_t num_bps = m_thread_observation_bps.size();
2321 if (num_bps != 0)
2322 {
2323 for (int i = 0; i < num_bps; i++)
2324 {
2325 lldb::BreakpointSP break_sp = m_target.GetBreakpointByID(m_thread_observation_bps[i]);
2326 if (break_sp)
2327 {
2328 if (log)
2329 log->Printf("Enabled noticing new thread breakpoint.");
2330 break_sp->SetEnabled(true);
2331 }
2332 }
2333 }
2334 else
2335 {
2336 for (int i = 0; bp_names[i] != NULL; i++)
2337 {
2338 Breakpoint *breakpoint = m_target.CreateBreakpoint (NULL, bp_names[i], eFunctionNameTypeFull, true).get();
2339 if (breakpoint)
2340 {
2341 if (log)
2342 log->Printf("Successfully created new thread notification breakpoint at \"%s\".", bp_names[i]);
2343 m_thread_observation_bps.push_back(breakpoint->GetID());
2344 breakpoint->SetCallback (ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
2345 }
2346 else
2347 {
2348 if (log)
2349 log->Printf("Failed to create new thread notification breakpoint.");
2350 return false;
2351 }
2352 }
2353 }
2354
2355 return true;
2356}
2357
2358bool
2359ProcessGDBRemote::StopNoticingNewThreads()
2360{
Jim Inghamff276fe2011-02-08 05:19:01 +00002361 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
2362 if (log)
2363 log->Printf ("Disabling new thread notification breakpoint.");
Jim Ingham55e01d82011-01-22 01:33:44 +00002364 size_t num_bps = m_thread_observation_bps.size();
2365 if (num_bps != 0)
2366 {
2367 for (int i = 0; i < num_bps; i++)
2368 {
Jim Ingham55e01d82011-01-22 01:33:44 +00002369
2370 lldb::BreakpointSP break_sp = m_target.GetBreakpointByID(m_thread_observation_bps[i]);
2371 if (break_sp)
2372 {
Jim Ingham55e01d82011-01-22 01:33:44 +00002373 break_sp->SetEnabled(false);
2374 }
2375 }
2376 }
2377 return true;
2378}
2379
2380