blob: 004beb6ea17ded5d9ab69ca7da45de4ed4ef3c92 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- GDBRemoteCommunication.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
11#include "GDBRemoteCommunication.h"
12
13// C Includes
14// C++ Includes
15// Other libraries and framework includes
Greg Clayton395fc332011-02-15 21:59:32 +000016#include "llvm/ADT/Triple.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000017#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Core/ConnectionFileDescriptor.h"
19#include "lldb/Core/Log.h"
20#include "lldb/Core/State.h"
21#include "lldb/Core/StreamString.h"
Greg Claytoncd548032011-02-01 01:31:41 +000022#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Host/TimeValue.h"
24
25// Project includes
Greg Clayton54e7afa2010-07-09 20:39:50 +000026#include "Utility/StringExtractorGDBRemote.h"
Chris Lattner24943d22010-06-08 16:52:24 +000027#include "ProcessGDBRemote.h"
28#include "ProcessGDBRemoteLog.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33//----------------------------------------------------------------------
34// GDBRemoteCommunication constructor
35//----------------------------------------------------------------------
36GDBRemoteCommunication::GDBRemoteCommunication() :
Greg Claytoneecb0f32010-12-04 02:39:47 +000037 Communication("gdb-remote.packets"),
Greg Claytonc1f45872011-02-12 06:28:37 +000038 m_supports_not_sending_acks (eLazyBoolCalculate),
39 m_supports_thread_suffix (eLazyBoolCalculate),
40 m_supports_qHostInfo (eLazyBoolCalculate),
41 m_supports_vCont_all (eLazyBoolCalculate),
42 m_supports_vCont_any (eLazyBoolCalculate),
43 m_supports_vCont_c (eLazyBoolCalculate),
44 m_supports_vCont_C (eLazyBoolCalculate),
45 m_supports_vCont_s (eLazyBoolCalculate),
46 m_supports_vCont_S (eLazyBoolCalculate),
Chris Lattner24943d22010-06-08 16:52:24 +000047 m_rx_packet_listener ("gdbremote.rx_packet"),
48 m_sequence_mutex (Mutex::eMutexTypeRecursive),
Greg Claytoncecf3482011-01-20 07:53:45 +000049 m_public_is_running (false),
50 m_private_is_running (false),
Chris Lattner24943d22010-06-08 16:52:24 +000051 m_async_mutex (Mutex::eMutexTypeRecursive),
52 m_async_packet_predicate (false),
53 m_async_packet (),
54 m_async_response (),
55 m_async_timeout (UINT32_MAX),
56 m_async_signal (-1),
57 m_arch(),
58 m_os(),
59 m_vendor(),
Greg Claytoncd548032011-02-01 01:31:41 +000060 m_byte_order(lldb::endian::InlHostByteOrder()),
Chris Lattner24943d22010-06-08 16:52:24 +000061 m_pointer_byte_size(0)
62{
63 m_rx_packet_listener.StartListeningForEvents(this,
64 Communication::eBroadcastBitPacketAvailable |
65 Communication::eBroadcastBitReadThreadDidExit);
66}
67
68//----------------------------------------------------------------------
69// Destructor
70//----------------------------------------------------------------------
71GDBRemoteCommunication::~GDBRemoteCommunication()
72{
73 m_rx_packet_listener.StopListeningForEvents(this,
74 Communication::eBroadcastBitPacketAvailable |
75 Communication::eBroadcastBitReadThreadDidExit);
76 if (IsConnected())
77 {
78 StopReadThread();
79 Disconnect();
80 }
81}
82
83
84char
85GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
86{
87 int checksum = 0;
88
89 // We only need to compute the checksum if we are sending acks
Greg Claytonc1f45872011-02-12 06:28:37 +000090 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +000091 {
Greg Clayton54e7afa2010-07-09 20:39:50 +000092 for (size_t i = 0; i < payload_length; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +000093 checksum += payload[i];
94 }
95 return checksum & 255;
96}
97
98size_t
Greg Claytona4881d02011-01-22 07:12:45 +000099GDBRemoteCommunication::SendAck ()
Chris Lattner24943d22010-06-08 16:52:24 +0000100{
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000101 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
102 if (log)
103 log->Printf ("send packet: +");
Chris Lattner24943d22010-06-08 16:52:24 +0000104 ConnectionStatus status = eConnectionStatusSuccess;
Greg Claytona4881d02011-01-22 07:12:45 +0000105 char ack_char = '+';
Chris Lattner24943d22010-06-08 16:52:24 +0000106 return Write (&ack_char, 1, status, NULL) == 1;
107}
108
109size_t
Greg Claytona4881d02011-01-22 07:12:45 +0000110GDBRemoteCommunication::SendNack ()
111{
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000112 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
113 if (log)
114 log->Printf ("send packet: -");
Greg Claytona4881d02011-01-22 07:12:45 +0000115 ConnectionStatus status = eConnectionStatusSuccess;
116 char nack_char = '-';
117 return Write (&nack_char, 1, status, NULL) == 1;
118}
119
Greg Claytonc1f45872011-02-12 06:28:37 +0000120bool
121GDBRemoteCommunication::GetSendAcks ()
122{
123 if (m_supports_not_sending_acks == eLazyBoolCalculate)
124 {
125 StringExtractorGDBRemote response;
126 m_supports_not_sending_acks = eLazyBoolNo;
127 if (SendPacketAndWaitForResponse("QStartNoAckMode", response, 1, false))
128 {
129 if (response.IsOKPacket())
130 m_supports_not_sending_acks = eLazyBoolYes;
131 }
132 }
133 return m_supports_not_sending_acks != eLazyBoolYes;
134}
135
136void
137GDBRemoteCommunication::ResetDiscoverableSettings()
138{
139 m_supports_not_sending_acks = eLazyBoolCalculate;
140 m_supports_thread_suffix = eLazyBoolCalculate;
141 m_supports_qHostInfo = eLazyBoolCalculate;
142 m_supports_vCont_c = eLazyBoolCalculate;
143 m_supports_vCont_C = eLazyBoolCalculate;
144 m_supports_vCont_s = eLazyBoolCalculate;
145 m_supports_vCont_S = eLazyBoolCalculate;
146 m_arch.Clear();
147 m_os.Clear();
148 m_vendor.Clear();
149 m_byte_order = lldb::endian::InlHostByteOrder();
150 m_pointer_byte_size = 0;
151}
152
153
154bool
155GDBRemoteCommunication::GetThreadSuffixSupported ()
156{
157 if (m_supports_thread_suffix == eLazyBoolCalculate)
158 {
159 StringExtractorGDBRemote response;
160 m_supports_thread_suffix = eLazyBoolNo;
161 if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, 1, false))
162 {
163 if (response.IsOKPacket())
164 m_supports_thread_suffix = eLazyBoolYes;
165 }
166 }
167 return m_supports_thread_suffix;
168}
169bool
170GDBRemoteCommunication::GetVContSupported (char flavor)
171{
172 if (m_supports_vCont_c == eLazyBoolCalculate)
173 {
174 StringExtractorGDBRemote response;
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000175 m_supports_vCont_any = eLazyBoolNo;
176 m_supports_vCont_all = eLazyBoolNo;
Greg Claytonc1f45872011-02-12 06:28:37 +0000177 m_supports_vCont_c = eLazyBoolNo;
178 m_supports_vCont_C = eLazyBoolNo;
179 m_supports_vCont_s = eLazyBoolNo;
180 m_supports_vCont_S = eLazyBoolNo;
181 if (SendPacketAndWaitForResponse("vCont?", response, 1, false))
182 {
183 const char *response_cstr = response.GetStringRef().c_str();
184 if (::strstr (response_cstr, ";c"))
185 m_supports_vCont_c = eLazyBoolYes;
186
187 if (::strstr (response_cstr, ";C"))
188 m_supports_vCont_C = eLazyBoolYes;
189
190 if (::strstr (response_cstr, ";s"))
191 m_supports_vCont_s = eLazyBoolYes;
192
193 if (::strstr (response_cstr, ";S"))
194 m_supports_vCont_S = eLazyBoolYes;
195
196 if (m_supports_vCont_c == eLazyBoolYes &&
197 m_supports_vCont_C == eLazyBoolYes &&
198 m_supports_vCont_s == eLazyBoolYes &&
199 m_supports_vCont_S == eLazyBoolYes)
200 {
201 m_supports_vCont_all = eLazyBoolYes;
202 }
203
204 if (m_supports_vCont_c == eLazyBoolYes ||
205 m_supports_vCont_C == eLazyBoolYes ||
206 m_supports_vCont_s == eLazyBoolYes ||
207 m_supports_vCont_S == eLazyBoolYes)
208 {
209 m_supports_vCont_any = eLazyBoolYes;
210 }
211 }
212 }
213
214 switch (flavor)
215 {
216 case 'a': return m_supports_vCont_any;
217 case 'A': return m_supports_vCont_all;
218 case 'c': return m_supports_vCont_c;
219 case 'C': return m_supports_vCont_C;
220 case 's': return m_supports_vCont_s;
221 case 'S': return m_supports_vCont_S;
222 default: break;
223 }
224 return false;
225}
226
227
Greg Claytona4881d02011-01-22 07:12:45 +0000228size_t
Chris Lattner24943d22010-06-08 16:52:24 +0000229GDBRemoteCommunication::SendPacketAndWaitForResponse
230(
231 const char *payload,
232 StringExtractorGDBRemote &response,
233 uint32_t timeout_seconds,
234 bool send_async
235)
236{
237 return SendPacketAndWaitForResponse (payload,
238 ::strlen (payload),
239 response,
240 timeout_seconds,
241 send_async);
242}
243
244size_t
245GDBRemoteCommunication::SendPacketAndWaitForResponse
246(
247 const char *payload,
248 size_t payload_length,
249 StringExtractorGDBRemote &response,
250 uint32_t timeout_seconds,
251 bool send_async
252)
253{
254 Mutex::Locker locker;
255 TimeValue timeout_time;
256 timeout_time = TimeValue::Now();
257 timeout_time.OffsetWithSeconds (timeout_seconds);
Greg Claytondb2bab42011-01-27 09:02:32 +0000258 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +0000259
Greg Clayton1a679462010-09-03 19:15:43 +0000260 if (GetSequenceMutex (locker))
Chris Lattner24943d22010-06-08 16:52:24 +0000261 {
262 if (SendPacketNoLock (payload, strlen(payload)))
263 return WaitForPacketNoLock (response, &timeout_time);
264 }
265 else
266 {
267 if (send_async)
268 {
269 Mutex::Locker async_locker (m_async_mutex);
270 m_async_packet.assign(payload, payload_length);
271 m_async_timeout = timeout_seconds;
272 m_async_packet_predicate.SetValue (true, eBroadcastNever);
273
Greg Claytondb2bab42011-01-27 09:02:32 +0000274 if (log)
275 log->Printf ("async: async packet = %s", m_async_packet.c_str());
276
Chris Lattner24943d22010-06-08 16:52:24 +0000277 bool timed_out = false;
Greg Claytona4881d02011-01-22 07:12:45 +0000278 bool sent_interrupt = false;
Greg Clayton68ca8232011-01-25 02:58:48 +0000279 if (SendInterrupt(locker, 2, sent_interrupt, timed_out))
Chris Lattner24943d22010-06-08 16:52:24 +0000280 {
Greg Claytondb2bab42011-01-27 09:02:32 +0000281 if (sent_interrupt)
Chris Lattner24943d22010-06-08 16:52:24 +0000282 {
Greg Claytondb2bab42011-01-27 09:02:32 +0000283 if (log)
284 log->Printf ("async: sent interrupt");
285 if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
286 {
287 if (log)
288 log->Printf ("async: got response");
289 response = m_async_response;
290 return response.GetStringRef().size();
291 }
292 else
293 {
294 if (log)
295 log->Printf ("async: timed out waiting for response");
296 }
297
298 // Make sure we wait until the continue packet has been sent again...
299 if (m_private_is_running.WaitForValueEqualTo (true, &timeout_time, &timed_out))
300 {
301 if (log)
302 log->Printf ("async: timed out waiting for process to resume");
303 }
304 }
305 else
306 {
307 // We had a racy condition where we went to send the interrupt
308 // yet we were able to get the loc
Chris Lattner24943d22010-06-08 16:52:24 +0000309 }
310 }
Greg Claytondb2bab42011-01-27 09:02:32 +0000311 else
312 {
313 if (log)
314 log->Printf ("async: failed to interrupt");
315 }
Chris Lattner24943d22010-06-08 16:52:24 +0000316 }
317 else
318 {
Greg Claytondb2bab42011-01-27 09:02:32 +0000319 if (log)
320 log->Printf ("mutex taken and send_async == false, aborting packet");
Chris Lattner24943d22010-06-08 16:52:24 +0000321 }
322 }
323 return 0;
324}
325
326//template<typename _Tp>
327//class ScopedValueChanger
328//{
329//public:
Greg Clayton5d187e52011-01-08 20:28:42 +0000330// // Take a value reference and the value to assign it to when this class
Chris Lattner24943d22010-06-08 16:52:24 +0000331// // instance goes out of scope.
332// ScopedValueChanger (_Tp &value_ref, _Tp value) :
333// m_value_ref (value_ref),
334// m_value (value)
335// {
336// }
337//
338// // This object is going out of scope, change the value pointed to by
339// // m_value_ref to the value we got during construction which was stored in
340// // m_value;
341// ~ScopedValueChanger ()
342// {
343// m_value_ref = m_value;
344// }
345//protected:
Greg Clayton5d187e52011-01-08 20:28:42 +0000346// _Tp &m_value_ref; // A reference to the value we will change when this object destructs
Chris Lattner24943d22010-06-08 16:52:24 +0000347// _Tp m_value; // The value to assign to m_value_ref when this goes out of scope.
348//};
349
350StateType
351GDBRemoteCommunication::SendContinuePacketAndWaitForResponse
352(
353 ProcessGDBRemote *process,
354 const char *payload,
355 size_t packet_length,
356 StringExtractorGDBRemote &response
357)
358{
Greg Claytone005f2c2010-11-06 01:53:30 +0000359 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +0000360 if (log)
361 log->Printf ("GDBRemoteCommunication::%s ()", __FUNCTION__);
362
363 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000364 StateType state = eStateRunning;
365
Greg Claytonb749a262010-12-03 06:02:24 +0000366 BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
Greg Claytoncecf3482011-01-20 07:53:45 +0000367 m_public_is_running.SetValue (true, eBroadcastNever);
Greg Claytondb2bab42011-01-27 09:02:32 +0000368 // Set the starting continue packet into "continue_packet". This packet
369 // make change if we are interrupted and we continue after an async packet...
370 std::string continue_packet(payload, packet_length);
371
Chris Lattner24943d22010-06-08 16:52:24 +0000372 while (state == eStateRunning)
373 {
374 if (log)
Greg Claytondb2bab42011-01-27 09:02:32 +0000375 log->Printf ("GDBRemoteCommunication::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
376 if (SendPacket(continue_packet.c_str(), continue_packet.size()) == 0)
377 state = eStateInvalid;
378
379 m_private_is_running.SetValue (true, eBroadcastNever);
380
381 if (log)
382 log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(%.*s)", __FUNCTION__);
Chris Lattner24943d22010-06-08 16:52:24 +0000383
384 if (WaitForPacket (response, (TimeValue*)NULL))
385 {
386 if (response.Empty())
387 state = eStateInvalid;
388 else
389 {
390 const char stop_type = response.GetChar();
391 if (log)
Greg Clayton68ca8232011-01-25 02:58:48 +0000392 log->Printf ("GDBRemoteCommunication::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000393 switch (stop_type)
394 {
395 case 'T':
396 case 'S':
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000397 if (process->GetStopID() == 0)
398 {
399 if (process->GetID() == LLDB_INVALID_PROCESS_ID)
400 {
401 lldb::pid_t pid = GetCurrentProcessID (1);
402 if (pid != LLDB_INVALID_PROCESS_ID)
403 process->SetID (pid);
404 }
405 process->BuildDynamicRegisterInfo (true);
406 }
407
Greg Claytoncecf3482011-01-20 07:53:45 +0000408 // Privately notify any internal threads that we have stopped
409 // in case we wanted to interrupt our process, yet we might
410 // send a packet and continue without returning control to the
411 // user.
412 m_private_is_running.SetValue (false, eBroadcastAlways);
Chris Lattner24943d22010-06-08 16:52:24 +0000413 if (m_async_signal != -1)
414 {
Greg Clayton68ca8232011-01-25 02:58:48 +0000415 if (log)
416 log->Printf ("async: send signo = %s", Host::GetSignalAsCString (m_async_signal));
Greg Claytonb4d1d332010-09-03 21:14:27 +0000417
Chris Lattner24943d22010-06-08 16:52:24 +0000418 // Save off the async signal we are supposed to send
419 const int async_signal = m_async_signal;
420 // Clear the async signal member so we don't end up
421 // sending the signal multiple times...
422 m_async_signal = -1;
423 // Check which signal we stopped with
424 uint8_t signo = response.GetHexU8(255);
425 if (signo == async_signal)
426 {
Greg Clayton68ca8232011-01-25 02:58:48 +0000427 if (log)
428 log->Printf ("async: stopped with signal %s, we are done running", Host::GetSignalAsCString (signo));
Greg Claytonb4d1d332010-09-03 21:14:27 +0000429
Chris Lattner24943d22010-06-08 16:52:24 +0000430 // We already stopped with a signal that we wanted
431 // to stop with, so we are done
432 response.SetFilePos (0);
433 }
434 else
435 {
436 // We stopped with a different signal that the one
437 // we wanted to stop with, so now we must resume
438 // with the signal we want
439 char signal_packet[32];
440 int signal_packet_len = 0;
441 signal_packet_len = ::snprintf (signal_packet,
442 sizeof (signal_packet),
443 "C%2.2x",
444 async_signal);
445
Greg Clayton68ca8232011-01-25 02:58:48 +0000446 if (log)
447 log->Printf ("async: stopped with signal %s, resume with %s",
Greg Claytonb4d1d332010-09-03 21:14:27 +0000448 Host::GetSignalAsCString (signo),
449 Host::GetSignalAsCString (async_signal));
450
Greg Claytondb2bab42011-01-27 09:02:32 +0000451 // Set the continue packet to resume...
452 continue_packet.assign(signal_packet, signal_packet_len);
453 continue;
Chris Lattner24943d22010-06-08 16:52:24 +0000454 }
455 }
456 else if (m_async_packet_predicate.GetValue())
457 {
458 // We are supposed to send an asynchronous packet while
459 // we are running.
460 m_async_response.Clear();
Greg Claytondb2bab42011-01-27 09:02:32 +0000461 if (m_async_packet.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000462 {
Greg Claytondb2bab42011-01-27 09:02:32 +0000463 if (log)
464 log->Printf ("async: error: empty async packet");
465
466 }
467 else
468 {
469 if (log)
470 log->Printf ("async: sending packet: %s",
471 m_async_packet.c_str());
472
Greg Clayton53d68e72010-07-20 22:52:08 +0000473 SendPacketAndWaitForResponse (&m_async_packet[0],
Chris Lattner24943d22010-06-08 16:52:24 +0000474 m_async_packet.size(),
475 m_async_response,
476 m_async_timeout,
477 false);
478 }
479 // Let the other thread that was trying to send the async
Greg Claytondb2bab42011-01-27 09:02:32 +0000480 // packet know that the packet has been sent and response is
481 // ready...
Chris Lattner24943d22010-06-08 16:52:24 +0000482 m_async_packet_predicate.SetValue(false, eBroadcastAlways);
483
Greg Claytondb2bab42011-01-27 09:02:32 +0000484 // Set the continue packet to resume...
485 continue_packet.assign (1, 'c');
486 continue;
Chris Lattner24943d22010-06-08 16:52:24 +0000487 }
488 // Stop with signal and thread info
489 state = eStateStopped;
490 break;
491
492 case 'W':
Greg Clayton68ca8232011-01-25 02:58:48 +0000493 case 'X':
Chris Lattner24943d22010-06-08 16:52:24 +0000494 // process exited
495 state = eStateExited;
496 break;
497
498 case 'O':
499 // STDOUT
500 {
501 std::string inferior_stdout;
502 inferior_stdout.reserve(response.GetBytesLeft () / 2);
503 char ch;
504 while ((ch = response.GetHexU8()) != '\0')
505 inferior_stdout.append(1, ch);
506 process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
507 }
508 break;
509
510 case 'E':
511 // ERROR
512 state = eStateInvalid;
513 break;
514
515 default:
516 if (log)
Greg Clayton68ca8232011-01-25 02:58:48 +0000517 log->Printf ("GDBRemoteCommunication::%s () unrecognized async packet", __FUNCTION__);
Greg Claytona2f74232011-02-24 22:24:29 +0000518 state = eStateInvalid;
Chris Lattner24943d22010-06-08 16:52:24 +0000519 break;
520 }
521 }
522 }
523 else
524 {
525 if (log)
526 log->Printf ("GDBRemoteCommunication::%s () WaitForPacket(...) => false", __FUNCTION__);
527 state = eStateInvalid;
528 }
529 }
530 if (log)
531 log->Printf ("GDBRemoteCommunication::%s () => %s", __FUNCTION__, StateAsCString(state));
532 response.SetFilePos(0);
Greg Claytoncecf3482011-01-20 07:53:45 +0000533 m_private_is_running.SetValue (false, eBroadcastAlways);
534 m_public_is_running.SetValue (false, eBroadcastAlways);
Chris Lattner24943d22010-06-08 16:52:24 +0000535 return state;
536}
537
538size_t
539GDBRemoteCommunication::SendPacket (const char *payload)
540{
541 Mutex::Locker locker(m_sequence_mutex);
542 return SendPacketNoLock (payload, ::strlen (payload));
543}
544
545size_t
546GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
547{
548 Mutex::Locker locker(m_sequence_mutex);
549 return SendPacketNoLock (payload, payload_length);
550}
551
552size_t
553GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
554{
555 if (IsConnected())
556 {
557 StreamString packet(0, 4, eByteOrderBig);
558
559 packet.PutChar('$');
560 packet.Write (payload, payload_length);
561 packet.PutChar('#');
562 packet.PutHex8(CalculcateChecksum (payload, payload_length));
563
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000564 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
565 if (log)
566 log->Printf ("send packet: %s", packet.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000567 ConnectionStatus status = eConnectionStatusSuccess;
568 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
569 if (bytes_written == packet.GetSize())
570 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000571 if (GetSendAcks ())
Greg Clayton54e7afa2010-07-09 20:39:50 +0000572 {
573 if (GetAck (1) != '+')
574 return 0;
575 }
Chris Lattner24943d22010-06-08 16:52:24 +0000576 }
Johnny Chen515ea542010-09-14 22:10:43 +0000577 else
578 {
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000579 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
580 if (log)
581 log->Printf ("error: failed to send packet: %s", packet.GetData());
Johnny Chen515ea542010-09-14 22:10:43 +0000582 }
Chris Lattner24943d22010-06-08 16:52:24 +0000583 return bytes_written;
Greg Claytoneea26402010-09-14 23:36:40 +0000584 }
Chris Lattner24943d22010-06-08 16:52:24 +0000585 return 0;
586}
587
588char
589GDBRemoteCommunication::GetAck (uint32_t timeout_seconds)
590{
591 StringExtractorGDBRemote response;
592 if (WaitForPacket (response, timeout_seconds) == 1)
593 return response.GetChar();
594 return 0;
595}
596
597bool
598GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
599{
600 return locker.TryLock (m_sequence_mutex.GetMutex());
601}
602
603bool
604GDBRemoteCommunication::SendAsyncSignal (int signo)
605{
606 m_async_signal = signo;
607 bool timed_out = false;
Greg Claytona4881d02011-01-22 07:12:45 +0000608 bool sent_interrupt = false;
Greg Clayton1a679462010-09-03 19:15:43 +0000609 Mutex::Locker locker;
Greg Claytona4881d02011-01-22 07:12:45 +0000610 if (SendInterrupt (locker, 1, sent_interrupt, timed_out))
Chris Lattner24943d22010-06-08 16:52:24 +0000611 return true;
612 m_async_signal = -1;
613 return false;
614}
615
Greg Clayton1a679462010-09-03 19:15:43 +0000616// This function takes a mutex locker as a parameter in case the GetSequenceMutex
617// actually succeeds. If it doesn't succeed in acquiring the sequence mutex
618// (the expected result), then it will send the halt packet. If it does succeed
619// then the caller that requested the interrupt will want to keep the sequence
620// locked down so that no one else can send packets while the caller has control.
621// This function usually gets called when we are running and need to stop the
622// target. It can also be used when we are running and and we need to do something
623// else (like read/write memory), so we need to interrupt the running process
624// (gdb remote protocol requires this), and do what we need to do, then resume.
625
Chris Lattner24943d22010-06-08 16:52:24 +0000626bool
Greg Claytona4881d02011-01-22 07:12:45 +0000627GDBRemoteCommunication::SendInterrupt
628(
629 Mutex::Locker& locker,
630 uint32_t seconds_to_wait_for_stop,
631 bool &sent_interrupt,
632 bool &timed_out
633)
Chris Lattner24943d22010-06-08 16:52:24 +0000634{
Greg Claytona4881d02011-01-22 07:12:45 +0000635 sent_interrupt = false;
636 timed_out = false;
Greg Claytondb2bab42011-01-27 09:02:32 +0000637 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Chris Lattner24943d22010-06-08 16:52:24 +0000638
Greg Claytondb2bab42011-01-27 09:02:32 +0000639 if (IsRunning())
Chris Lattner24943d22010-06-08 16:52:24 +0000640 {
641 // Only send an interrupt if our debugserver is running...
Greg Clayton1a679462010-09-03 19:15:43 +0000642 if (GetSequenceMutex (locker) == false)
Chris Lattner24943d22010-06-08 16:52:24 +0000643 {
644 // Someone has the mutex locked waiting for a response or for the
645 // inferior to stop, so send the interrupt on the down low...
646 char ctrl_c = '\x03';
647 ConnectionStatus status = eConnectionStatusSuccess;
648 TimeValue timeout;
649 if (seconds_to_wait_for_stop)
650 {
651 timeout = TimeValue::Now();
652 timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
653 }
Greg Claytondb2bab42011-01-27 09:02:32 +0000654 size_t bytes_written = Write (&ctrl_c, 1, status, NULL);
Greg Clayton68ca8232011-01-25 02:58:48 +0000655 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_PROCESS, "send packet: \\x03");
Greg Claytondb2bab42011-01-27 09:02:32 +0000656 if (bytes_written > 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000657 {
Greg Claytona4881d02011-01-22 07:12:45 +0000658 sent_interrupt = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000659 if (seconds_to_wait_for_stop)
Greg Claytondb2bab42011-01-27 09:02:32 +0000660 {
Greg Clayton1c2aa462011-02-03 01:07:45 +0000661 if (m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out))
662 {
663 if (log)
664 log->Printf ("GDBRemoteCommunication::%s () - sent interrupt, private state stopped", __FUNCTION__);
665 return true;
666 }
667 else
668 {
669 if (log)
670 log->Printf ("GDBRemoteCommunication::%s () - sent interrupt, timed out wating for async thread resume", __FUNCTION__);
671 }
Greg Claytondb2bab42011-01-27 09:02:32 +0000672 }
673 else
674 {
675 if (log)
676 log->Printf ("GDBRemoteCommunication::%s () - sent interrupt, not waiting for stop...", __FUNCTION__);
Greg Clayton1c2aa462011-02-03 01:07:45 +0000677 return true;
Greg Claytondb2bab42011-01-27 09:02:32 +0000678 }
Chris Lattner24943d22010-06-08 16:52:24 +0000679 }
Greg Claytondb2bab42011-01-27 09:02:32 +0000680 else
681 {
682 if (log)
683 log->Printf ("GDBRemoteCommunication::%s () - failed to write interrupt", __FUNCTION__);
684 }
Greg Clayton1c2aa462011-02-03 01:07:45 +0000685 return false;
Greg Claytondb2bab42011-01-27 09:02:32 +0000686 }
687 else
688 {
689 if (log)
690 log->Printf ("GDBRemoteCommunication::%s () - got sequence mutex without having to interrupt", __FUNCTION__);
Chris Lattner24943d22010-06-08 16:52:24 +0000691 }
692 }
Greg Clayton1c2aa462011-02-03 01:07:45 +0000693 return true;
Chris Lattner24943d22010-06-08 16:52:24 +0000694}
695
Greg Clayton72e1c782011-01-22 23:43:18 +0000696bool
697GDBRemoteCommunication::WaitForNotRunning (const TimeValue *timeout_ptr)
698{
699 return m_public_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
700}
701
702bool
703GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
704{
705 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
706}
707
Chris Lattner24943d22010-06-08 16:52:24 +0000708size_t
709GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, uint32_t timeout_seconds)
710{
Greg Claytoncecf3482011-01-20 07:53:45 +0000711 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000712 TimeValue timeout_time;
713 timeout_time = TimeValue::Now();
714 timeout_time.OffsetWithSeconds (timeout_seconds);
715 return WaitForPacketNoLock (response, &timeout_time);
716}
717
718size_t
Greg Clayton72e1c782011-01-22 23:43:18 +0000719GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &response, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000720{
721 Mutex::Locker locker(m_sequence_mutex);
722 return WaitForPacketNoLock (response, timeout_time_ptr);
723}
724
725size_t
Greg Clayton72e1c782011-01-22 23:43:18 +0000726GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000727{
728 bool checksum_error = false;
729 response.Clear ();
730
731 EventSP event_sp;
732
733 if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
734 {
735 const uint32_t event_type = event_sp->GetType();
736 if (event_type | Communication::eBroadcastBitPacketAvailable)
737 {
738 const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
739 if (event_bytes)
740 {
741 const char * packet_data = (const char *)event_bytes->GetBytes();
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000742 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
743 if (log)
744 log->Printf ("read packet: %s", packet_data);
Chris Lattner24943d22010-06-08 16:52:24 +0000745 const size_t packet_size = event_bytes->GetByteSize();
746 if (packet_data && packet_size > 0)
747 {
748 std::string &response_str = response.GetStringRef();
749 if (packet_data[0] == '$')
750 {
Greg Clayton4862fa22011-01-08 03:17:57 +0000751 bool success = false;
752 if (packet_size < 4)
753 ::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
754 else if (packet_data[packet_size-3] != '#' ||
755 !::isxdigit (packet_data[packet_size-2]) ||
756 !::isxdigit (packet_data[packet_size-1]))
757 ::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
758 else
759 success = true;
760
761 if (success)
762 response_str.assign (packet_data + 1, packet_size - 4);
Greg Claytonc1f45872011-02-12 06:28:37 +0000763 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +0000764 {
765 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
Greg Clayton53d68e72010-07-20 22:52:08 +0000766 char actual_checksum = CalculcateChecksum (&response_str[0], response_str.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000767 checksum_error = packet_checksum != actual_checksum;
768 // Send the ack or nack if needed
Greg Clayton4862fa22011-01-08 03:17:57 +0000769 if (checksum_error || !success)
Greg Claytona4881d02011-01-22 07:12:45 +0000770 SendNack();
Chris Lattner24943d22010-06-08 16:52:24 +0000771 else
Greg Claytona4881d02011-01-22 07:12:45 +0000772 SendAck();
Chris Lattner24943d22010-06-08 16:52:24 +0000773 }
774 }
775 else
776 {
777 response_str.assign (packet_data, packet_size);
778 }
779 return response_str.size();
780 }
781 }
782 }
783 else if (Communication::eBroadcastBitReadThreadDidExit)
784 {
785 // Our read thread exited on us so just fall through and return zero...
786 }
787 }
788 return 0;
789}
790
791void
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000792GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
793 ConnectionStatus status)
Chris Lattner24943d22010-06-08 16:52:24 +0000794{
795 // Put the packet data into the buffer in a thread safe fashion
796 Mutex::Locker locker(m_bytes_mutex);
797 m_bytes.append ((const char *)src, src_len);
798
799 // Parse up the packets into gdb remote packets
800 while (!m_bytes.empty())
801 {
802 // end_idx must be one past the last valid packet byte. Start
803 // it off with an invalid value that is the same as the current
804 // index.
805 size_t end_idx = 0;
806
807 switch (m_bytes[0])
808 {
809 case '+': // Look for ack
810 case '-': // Look for cancel
811 case '\x03': // ^C to halt target
812 end_idx = 1; // The command is one byte long...
813 break;
814
815 case '$':
816 // Look for a standard gdb packet?
817 end_idx = m_bytes.find('#');
818 if (end_idx != std::string::npos)
819 {
820 if (end_idx + 2 < m_bytes.size())
821 {
822 end_idx += 3;
823 }
824 else
825 {
826 // Checksum bytes aren't all here yet
827 end_idx = std::string::npos;
828 }
829 }
830 break;
831
832 default:
833 break;
834 }
835
836 if (end_idx == std::string::npos)
837 {
838 //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
839 return;
840 }
841 else if (end_idx > 0)
842 {
843 // We have a valid packet...
844 assert (end_idx <= m_bytes.size());
845 std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
846 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
847 BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
848 m_bytes.erase(0, end_idx);
849 }
850 else
851 {
852 assert (1 <= m_bytes.size());
853 ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
854 m_bytes.erase(0, 1);
855 }
856 }
857}
858
859lldb::pid_t
860GDBRemoteCommunication::GetCurrentProcessID (uint32_t timeout_seconds)
861{
862 StringExtractorGDBRemote response;
863 if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, timeout_seconds, false))
864 {
865 if (response.GetChar() == 'Q')
866 if (response.GetChar() == 'C')
867 return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
868 }
869 return LLDB_INVALID_PROCESS_ID;
870}
871
872bool
873GDBRemoteCommunication::GetLaunchSuccess (uint32_t timeout_seconds, std::string &error_str)
874{
875 error_str.clear();
876 StringExtractorGDBRemote response;
877 if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, timeout_seconds, false))
878 {
879 if (response.IsOKPacket())
880 return true;
881 if (response.GetChar() == 'E')
882 {
883 // A string the describes what failed when launching...
884 error_str = response.GetStringRef().substr(1);
885 }
886 else
887 {
888 error_str.assign ("unknown error occurred launching process");
889 }
890 }
891 else
892 {
893 error_str.assign ("failed to send the qLaunchSuccess packet");
894 }
895 return false;
896}
897
898int
899GDBRemoteCommunication::SendArgumentsPacket (char const *argv[], uint32_t timeout_seconds)
900{
901 if (argv && argv[0])
902 {
903 StreamString packet;
904 packet.PutChar('A');
905 const char *arg;
906 for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
907 {
908 const int arg_len = strlen(arg);
909 if (i > 0)
910 packet.PutChar(',');
911 packet.Printf("%i,%i,", arg_len * 2, i);
Greg Claytona2f74232011-02-24 22:24:29 +0000912 packet.PutBytesAsRawHex8 (arg, arg_len);
Chris Lattner24943d22010-06-08 16:52:24 +0000913 }
914
915 StringExtractorGDBRemote response;
916 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
917 {
918 if (response.IsOKPacket())
919 return 0;
920 uint8_t error = response.GetError();
921 if (error)
922 return error;
923 }
924 }
925 return -1;
926}
927
928int
929GDBRemoteCommunication::SendEnvironmentPacket (char const *name_equal_value, uint32_t timeout_seconds)
930{
931 if (name_equal_value && name_equal_value[0])
932 {
933 StreamString packet;
934 packet.Printf("QEnvironment:%s", name_equal_value);
935 StringExtractorGDBRemote response;
936 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
937 {
938 if (response.IsOKPacket())
939 return 0;
940 uint8_t error = response.GetError();
941 if (error)
942 return error;
943 }
944 }
945 return -1;
946}
947
948bool
Greg Claytonc1f45872011-02-12 06:28:37 +0000949GDBRemoteCommunication::GetHostInfo ()
Chris Lattner24943d22010-06-08 16:52:24 +0000950{
Greg Claytonc1f45872011-02-12 06:28:37 +0000951 if (m_supports_qHostInfo == eLazyBoolCalculate)
Chris Lattner24943d22010-06-08 16:52:24 +0000952 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000953 m_supports_qHostInfo = eLazyBoolNo;
Chris Lattner24943d22010-06-08 16:52:24 +0000954
Greg Claytonc1f45872011-02-12 06:28:37 +0000955 StringExtractorGDBRemote response;
956 if (SendPacketAndWaitForResponse ("qHostInfo", response, 1, false))
Chris Lattner24943d22010-06-08 16:52:24 +0000957 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000958 if (response.IsUnsupportedPacket())
959 return false;
960
961 m_supports_qHostInfo = eLazyBoolYes;
962
963 std::string name;
964 std::string value;
965 uint32_t cpu = LLDB_INVALID_CPUTYPE;
966 uint32_t sub = 0;
Greg Claytone71e2582011-02-04 01:58:07 +0000967
Greg Claytonc1f45872011-02-12 06:28:37 +0000968 while (response.GetNameColonValue(name, value))
969 {
970 if (name.compare("cputype") == 0)
971 {
972 // exception type in big endian hex
973 cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
974 }
975 else if (name.compare("cpusubtype") == 0)
976 {
977 // exception count in big endian hex
978 sub = Args::StringToUInt32 (value.c_str(), 0, 0);
979 }
980 else if (name.compare("ostype") == 0)
981 {
982 // exception data in big endian hex
983 m_os.SetCString(value.c_str());
984 }
985 else if (name.compare("vendor") == 0)
986 {
987 m_vendor.SetCString(value.c_str());
988 }
989 else if (name.compare("endian") == 0)
990 {
991 if (value.compare("little") == 0)
992 m_byte_order = eByteOrderLittle;
993 else if (value.compare("big") == 0)
994 m_byte_order = eByteOrderBig;
995 else if (value.compare("pdp") == 0)
996 m_byte_order = eByteOrderPDP;
997 }
998 else if (name.compare("ptrsize") == 0)
999 {
1000 m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
1001 }
1002 }
1003
1004 if (cpu != LLDB_INVALID_CPUTYPE)
Greg Clayton940b1032011-02-23 00:35:02 +00001005 m_arch.SetArchitecture (lldb::eArchTypeMachO, cpu, sub);
Greg Claytonc1f45872011-02-12 06:28:37 +00001006 }
Chris Lattner24943d22010-06-08 16:52:24 +00001007 }
Greg Claytonc1f45872011-02-12 06:28:37 +00001008 return m_supports_qHostInfo == eLazyBoolYes;
Chris Lattner24943d22010-06-08 16:52:24 +00001009}
1010
1011int
1012GDBRemoteCommunication::SendAttach
1013(
1014 lldb::pid_t pid,
1015 uint32_t timeout_seconds,
1016 StringExtractorGDBRemote& response
1017)
1018{
1019 if (pid != LLDB_INVALID_PROCESS_ID)
1020 {
1021 StreamString packet;
1022 packet.Printf("vAttach;%x", pid);
1023
1024 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, timeout_seconds, false))
1025 {
1026 if (response.IsErrorPacket())
1027 return response.GetError();
1028 return 0;
1029 }
1030 }
1031 return -1;
1032}
1033
1034const lldb_private::ArchSpec &
1035GDBRemoteCommunication::GetHostArchitecture ()
1036{
1037 if (!HostInfoIsValid ())
Greg Claytonc1f45872011-02-12 06:28:37 +00001038 GetHostInfo ();
Chris Lattner24943d22010-06-08 16:52:24 +00001039 return m_arch;
1040}
1041
1042const lldb_private::ConstString &
1043GDBRemoteCommunication::GetOSString ()
1044{
1045 if (!HostInfoIsValid ())
Greg Claytonc1f45872011-02-12 06:28:37 +00001046 GetHostInfo ();
Chris Lattner24943d22010-06-08 16:52:24 +00001047 return m_os;
1048}
1049
1050const lldb_private::ConstString &
1051GDBRemoteCommunication::GetVendorString()
1052{
1053 if (!HostInfoIsValid ())
Greg Claytonc1f45872011-02-12 06:28:37 +00001054 GetHostInfo ();
Chris Lattner24943d22010-06-08 16:52:24 +00001055 return m_vendor;
1056}
1057
1058lldb::ByteOrder
1059GDBRemoteCommunication::GetByteOrder ()
1060{
1061 if (!HostInfoIsValid ())
Greg Claytonc1f45872011-02-12 06:28:37 +00001062 GetHostInfo ();
Chris Lattner24943d22010-06-08 16:52:24 +00001063 return m_byte_order;
1064}
1065
1066uint32_t
1067GDBRemoteCommunication::GetAddressByteSize ()
1068{
1069 if (!HostInfoIsValid ())
Greg Claytonc1f45872011-02-12 06:28:37 +00001070 GetHostInfo ();
Chris Lattner24943d22010-06-08 16:52:24 +00001071 return m_pointer_byte_size;
1072}
1073
1074addr_t
1075GDBRemoteCommunication::AllocateMemory (size_t size, uint32_t permissions, uint32_t timeout_seconds)
1076{
1077 char packet[64];
1078 ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
1079 permissions & lldb::ePermissionsReadable ? "r" : "",
1080 permissions & lldb::ePermissionsWritable ? "w" : "",
1081 permissions & lldb::ePermissionsExecutable ? "x" : "");
1082 StringExtractorGDBRemote response;
1083 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
1084 {
1085 if (!response.IsErrorPacket())
1086 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
1087 }
1088 return LLDB_INVALID_ADDRESS;
1089}
1090
1091bool
1092GDBRemoteCommunication::DeallocateMemory (addr_t addr, uint32_t timeout_seconds)
1093{
1094 char packet[64];
1095 snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
1096 StringExtractorGDBRemote response;
1097 if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
1098 {
Sean Callanan6a925532011-01-13 08:53:35 +00001099 if (response.IsOKPacket())
Chris Lattner24943d22010-06-08 16:52:24 +00001100 return true;
1101 }
1102 return false;
1103}
Jim Ingham3ae449a2010-11-17 02:32:00 +00001104
Greg Claytona2f74232011-02-24 22:24:29 +00001105int
1106GDBRemoteCommunication::SetSTDIN (char const *path)
1107{
1108 if (path && path[0])
1109 {
1110 StreamString packet;
1111 packet.PutCString("QSetSTDIN:");
1112 packet.PutBytesAsRawHex8(path, strlen(path));
1113
1114 StringExtractorGDBRemote response;
1115 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, 1, false))
1116 {
1117 if (response.IsOKPacket())
1118 return 0;
1119 uint8_t error = response.GetError();
1120 if (error)
1121 return error;
1122 }
1123 }
1124 return -1;
1125}
1126
1127int
1128GDBRemoteCommunication::SetSTDOUT (char const *path)
1129{
1130 if (path && path[0])
1131 {
1132 StreamString packet;
1133 packet.PutCString("QSetSTDOUT:");
1134 packet.PutBytesAsRawHex8(path, strlen(path));
1135
1136 StringExtractorGDBRemote response;
1137 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, 1, false))
1138 {
1139 if (response.IsOKPacket())
1140 return 0;
1141 uint8_t error = response.GetError();
1142 if (error)
1143 return error;
1144 }
1145 }
1146 return -1;
1147}
1148
1149int
1150GDBRemoteCommunication::SetSTDERR (char const *path)
1151{
1152 if (path && path[0])
1153 {
1154 StreamString packet;
1155 packet.PutCString("QSetSTDERR:");
1156 packet.PutBytesAsRawHex8(path, strlen(path));
1157
1158 StringExtractorGDBRemote response;
1159 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, 1, false))
1160 {
1161 if (response.IsOKPacket())
1162 return 0;
1163 uint8_t error = response.GetError();
1164 if (error)
1165 return error;
1166 }
1167 }
1168 return -1;
1169}
1170
1171int
1172GDBRemoteCommunication::SetWorkingDir (char const *path)
1173{
1174 if (path && path[0])
1175 {
1176 StreamString packet;
1177 packet.PutCString("QSetWorkingDir:");
1178 packet.PutBytesAsRawHex8(path, strlen(path));
1179
1180 StringExtractorGDBRemote response;
1181 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, 1, false))
1182 {
1183 if (response.IsOKPacket())
1184 return 0;
1185 uint8_t error = response.GetError();
1186 if (error)
1187 return error;
1188 }
1189 }
1190 return -1;
1191}
1192
1193int
1194GDBRemoteCommunication::SetDisableASLR (bool enable)
1195{
1196 StreamString packet;
1197 packet.Printf("QSetDisableASLR:%i", enable ? 1 : 0);
1198
1199 StringExtractorGDBRemote response;
1200 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, 1, false))
1201 {
1202 if (response.IsOKPacket())
1203 return 0;
1204 uint8_t error = response.GetError();
1205 if (error)
1206 return error;
1207 }
1208 return -1;
1209}