blob: b4fb6f2ddfe30aa8c0db513cab0a73454971fb02 [file] [log] [blame]
Greg Clayton61d043b2011-03-22 04:00:09 +00001//===-- GDBRemoteCommunicationClient.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 "GDBRemoteCommunicationClient.h"
12
13// C Includes
14// C++ Includes
15// Other libraries and framework includes
16#include "llvm/ADT/Triple.h"
17#include "lldb/Interpreter/Args.h"
18#include "lldb/Core/ConnectionFileDescriptor.h"
19#include "lldb/Core/Log.h"
20#include "lldb/Core/State.h"
21#include "lldb/Core/StreamString.h"
22#include "lldb/Host/Endian.h"
23#include "lldb/Host/Host.h"
24#include "lldb/Host/TimeValue.h"
25
26// Project includes
27#include "Utility/StringExtractorGDBRemote.h"
28#include "ProcessGDBRemote.h"
29#include "ProcessGDBRemoteLog.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
34//----------------------------------------------------------------------
35// GDBRemoteCommunicationClient constructor
36//----------------------------------------------------------------------
37GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
38 GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"),
39 m_supports_not_sending_acks (eLazyBoolCalculate),
40 m_supports_thread_suffix (eLazyBoolCalculate),
41 m_supports_qHostInfo (eLazyBoolCalculate),
42 m_supports_vCont_all (eLazyBoolCalculate),
43 m_supports_vCont_any (eLazyBoolCalculate),
44 m_supports_vCont_c (eLazyBoolCalculate),
45 m_supports_vCont_C (eLazyBoolCalculate),
46 m_supports_vCont_s (eLazyBoolCalculate),
47 m_supports_vCont_S (eLazyBoolCalculate),
48 m_async_mutex (Mutex::eMutexTypeRecursive),
49 m_async_packet_predicate (false),
50 m_async_packet (),
51 m_async_response (),
52 m_async_signal (-1),
53 m_arch(),
54 m_os(),
55 m_vendor(),
56 m_byte_order(lldb::endian::InlHostByteOrder()),
57 m_pointer_byte_size(0)
58{
59 m_rx_packet_listener.StartListeningForEvents(this,
60 Communication::eBroadcastBitPacketAvailable |
61 Communication::eBroadcastBitReadThreadDidExit);
62}
63
64//----------------------------------------------------------------------
65// Destructor
66//----------------------------------------------------------------------
67GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient()
68{
69 m_rx_packet_listener.StopListeningForEvents(this,
70 Communication::eBroadcastBitPacketAvailable |
71 Communication::eBroadcastBitReadThreadDidExit);
72 if (IsConnected())
73 {
74 StopReadThread();
75 Disconnect();
76 }
77}
78
79bool
80GDBRemoteCommunicationClient::GetSendAcks ()
81{
82 if (m_supports_not_sending_acks == eLazyBoolCalculate)
83 {
84 StringExtractorGDBRemote response;
85 m_supports_not_sending_acks = eLazyBoolNo;
86 if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false))
87 {
88 if (response.IsOKResponse())
89 m_supports_not_sending_acks = eLazyBoolYes;
90 }
91 }
92 return m_supports_not_sending_acks != eLazyBoolYes;
93}
94
95void
96GDBRemoteCommunicationClient::ResetDiscoverableSettings()
97{
98 m_supports_not_sending_acks = eLazyBoolCalculate;
99 m_supports_thread_suffix = eLazyBoolCalculate;
100 m_supports_qHostInfo = eLazyBoolCalculate;
101 m_supports_vCont_c = eLazyBoolCalculate;
102 m_supports_vCont_C = eLazyBoolCalculate;
103 m_supports_vCont_s = eLazyBoolCalculate;
104 m_supports_vCont_S = eLazyBoolCalculate;
105 m_arch.Clear();
106 m_os.Clear();
107 m_vendor.Clear();
108 m_byte_order = lldb::endian::InlHostByteOrder();
109 m_pointer_byte_size = 0;
110}
111
112
113bool
114GDBRemoteCommunicationClient::GetThreadSuffixSupported ()
115{
116 if (m_supports_thread_suffix == eLazyBoolCalculate)
117 {
118 StringExtractorGDBRemote response;
119 m_supports_thread_suffix = eLazyBoolNo;
120 if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false))
121 {
122 if (response.IsOKResponse())
123 m_supports_thread_suffix = eLazyBoolYes;
124 }
125 }
126 return m_supports_thread_suffix;
127}
128bool
129GDBRemoteCommunicationClient::GetVContSupported (char flavor)
130{
131 if (m_supports_vCont_c == eLazyBoolCalculate)
132 {
133 StringExtractorGDBRemote response;
134 m_supports_vCont_any = eLazyBoolNo;
135 m_supports_vCont_all = eLazyBoolNo;
136 m_supports_vCont_c = eLazyBoolNo;
137 m_supports_vCont_C = eLazyBoolNo;
138 m_supports_vCont_s = eLazyBoolNo;
139 m_supports_vCont_S = eLazyBoolNo;
140 if (SendPacketAndWaitForResponse("vCont?", response, false))
141 {
142 const char *response_cstr = response.GetStringRef().c_str();
143 if (::strstr (response_cstr, ";c"))
144 m_supports_vCont_c = eLazyBoolYes;
145
146 if (::strstr (response_cstr, ";C"))
147 m_supports_vCont_C = eLazyBoolYes;
148
149 if (::strstr (response_cstr, ";s"))
150 m_supports_vCont_s = eLazyBoolYes;
151
152 if (::strstr (response_cstr, ";S"))
153 m_supports_vCont_S = eLazyBoolYes;
154
155 if (m_supports_vCont_c == eLazyBoolYes &&
156 m_supports_vCont_C == eLazyBoolYes &&
157 m_supports_vCont_s == eLazyBoolYes &&
158 m_supports_vCont_S == eLazyBoolYes)
159 {
160 m_supports_vCont_all = eLazyBoolYes;
161 }
162
163 if (m_supports_vCont_c == eLazyBoolYes ||
164 m_supports_vCont_C == eLazyBoolYes ||
165 m_supports_vCont_s == eLazyBoolYes ||
166 m_supports_vCont_S == eLazyBoolYes)
167 {
168 m_supports_vCont_any = eLazyBoolYes;
169 }
170 }
171 }
172
173 switch (flavor)
174 {
175 case 'a': return m_supports_vCont_any;
176 case 'A': return m_supports_vCont_all;
177 case 'c': return m_supports_vCont_c;
178 case 'C': return m_supports_vCont_C;
179 case 's': return m_supports_vCont_s;
180 case 'S': return m_supports_vCont_S;
181 default: break;
182 }
183 return false;
184}
185
186
187size_t
188GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
189(
190 const char *payload,
191 StringExtractorGDBRemote &response,
192 bool send_async
193)
194{
195 return SendPacketAndWaitForResponse (payload,
196 ::strlen (payload),
197 response,
198 send_async);
199}
200
201size_t
202GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
203(
204 const char *payload,
205 size_t payload_length,
206 StringExtractorGDBRemote &response,
207 bool send_async
208)
209{
210 Mutex::Locker locker;
211 TimeValue timeout_time;
212 timeout_time = TimeValue::Now();
213 timeout_time.OffsetWithSeconds (m_packet_timeout);
214 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
215
216 if (GetSequenceMutex (locker))
217 {
218 if (SendPacketNoLock (payload, strlen(payload)))
219 return WaitForPacketNoLock (response, &timeout_time);
220 }
221 else
222 {
223 if (send_async)
224 {
225 Mutex::Locker async_locker (m_async_mutex);
226 m_async_packet.assign(payload, payload_length);
227 m_async_packet_predicate.SetValue (true, eBroadcastNever);
228
229 if (log)
230 log->Printf ("async: async packet = %s", m_async_packet.c_str());
231
232 bool timed_out = false;
233 bool sent_interrupt = false;
234 if (SendInterrupt(locker, 2, sent_interrupt, timed_out))
235 {
236 if (sent_interrupt)
237 {
238 if (log)
239 log->Printf ("async: sent interrupt");
240 if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
241 {
242 if (log)
243 log->Printf ("async: got response");
244 response = m_async_response;
245 return response.GetStringRef().size();
246 }
247 else
248 {
249 if (log)
250 log->Printf ("async: timed out waiting for response");
251 }
252
253 // Make sure we wait until the continue packet has been sent again...
254 if (m_private_is_running.WaitForValueEqualTo (true, &timeout_time, &timed_out))
255 {
256 if (log)
257 log->Printf ("async: timed out waiting for process to resume");
258 }
259 }
260 else
261 {
262 // We had a racy condition where we went to send the interrupt
263 // yet we were able to get the loc
264 }
265 }
266 else
267 {
268 if (log)
269 log->Printf ("async: failed to interrupt");
270 }
271 }
272 else
273 {
274 if (log)
275 log->Printf ("mutex taken and send_async == false, aborting packet");
276 }
277 }
278 return 0;
279}
280
281//template<typename _Tp>
282//class ScopedValueChanger
283//{
284//public:
285// // Take a value reference and the value to assign it to when this class
286// // instance goes out of scope.
287// ScopedValueChanger (_Tp &value_ref, _Tp value) :
288// m_value_ref (value_ref),
289// m_value (value)
290// {
291// }
292//
293// // This object is going out of scope, change the value pointed to by
294// // m_value_ref to the value we got during construction which was stored in
295// // m_value;
296// ~ScopedValueChanger ()
297// {
298// m_value_ref = m_value;
299// }
300//protected:
301// _Tp &m_value_ref; // A reference to the value we will change when this object destructs
302// _Tp m_value; // The value to assign to m_value_ref when this goes out of scope.
303//};
304
305StateType
306GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
307(
308 ProcessGDBRemote *process,
309 const char *payload,
310 size_t packet_length,
311 StringExtractorGDBRemote &response
312)
313{
314 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
315 if (log)
316 log->Printf ("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
317
318 Mutex::Locker locker(m_sequence_mutex);
319 StateType state = eStateRunning;
320
321 BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
322 m_public_is_running.SetValue (true, eBroadcastNever);
323 // Set the starting continue packet into "continue_packet". This packet
324 // make change if we are interrupted and we continue after an async packet...
325 std::string continue_packet(payload, packet_length);
326
327 while (state == eStateRunning)
328 {
329 if (log)
330 log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
331 if (SendPacket(continue_packet.c_str(), continue_packet.size()) == 0)
332 state = eStateInvalid;
333
334 m_private_is_running.SetValue (true, eBroadcastNever);
335
336 if (log)
337 log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%.*s)", __FUNCTION__);
338
339 if (WaitForPacket (response, (TimeValue*)NULL))
340 {
341 if (response.Empty())
342 state = eStateInvalid;
343 else
344 {
345 const char stop_type = response.GetChar();
346 if (log)
347 log->Printf ("GDBRemoteCommunicationClient::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str());
348 switch (stop_type)
349 {
350 case 'T':
351 case 'S':
352 if (process->GetStopID() == 0)
353 {
354 if (process->GetID() == LLDB_INVALID_PROCESS_ID)
355 {
356 lldb::pid_t pid = GetCurrentProcessID ();
357 if (pid != LLDB_INVALID_PROCESS_ID)
358 process->SetID (pid);
359 }
360 process->BuildDynamicRegisterInfo (true);
361 }
362
363 // Privately notify any internal threads that we have stopped
364 // in case we wanted to interrupt our process, yet we might
365 // send a packet and continue without returning control to the
366 // user.
367 m_private_is_running.SetValue (false, eBroadcastAlways);
368 if (m_async_signal != -1)
369 {
370 if (log)
371 log->Printf ("async: send signo = %s", Host::GetSignalAsCString (m_async_signal));
372
373 // Save off the async signal we are supposed to send
374 const int async_signal = m_async_signal;
375 // Clear the async signal member so we don't end up
376 // sending the signal multiple times...
377 m_async_signal = -1;
378 // Check which signal we stopped with
379 uint8_t signo = response.GetHexU8(255);
380 if (signo == async_signal)
381 {
382 if (log)
383 log->Printf ("async: stopped with signal %s, we are done running", Host::GetSignalAsCString (signo));
384
385 // We already stopped with a signal that we wanted
386 // to stop with, so we are done
387 response.SetFilePos (0);
388 }
389 else
390 {
391 // We stopped with a different signal that the one
392 // we wanted to stop with, so now we must resume
393 // with the signal we want
394 char signal_packet[32];
395 int signal_packet_len = 0;
396 signal_packet_len = ::snprintf (signal_packet,
397 sizeof (signal_packet),
398 "C%2.2x",
399 async_signal);
400
401 if (log)
402 log->Printf ("async: stopped with signal %s, resume with %s",
403 Host::GetSignalAsCString (signo),
404 Host::GetSignalAsCString (async_signal));
405
406 // Set the continue packet to resume...
407 continue_packet.assign(signal_packet, signal_packet_len);
408 continue;
409 }
410 }
411 else if (m_async_packet_predicate.GetValue())
412 {
413 // We are supposed to send an asynchronous packet while
414 // we are running.
415 m_async_response.Clear();
416 if (m_async_packet.empty())
417 {
418 if (log)
419 log->Printf ("async: error: empty async packet");
420
421 }
422 else
423 {
424 if (log)
425 log->Printf ("async: sending packet: %s",
426 m_async_packet.c_str());
427
428 SendPacketAndWaitForResponse (&m_async_packet[0],
429 m_async_packet.size(),
430 m_async_response,
431 false);
432 }
433 // Let the other thread that was trying to send the async
434 // packet know that the packet has been sent and response is
435 // ready...
436 m_async_packet_predicate.SetValue(false, eBroadcastAlways);
437
438 // Set the continue packet to resume...
439 continue_packet.assign (1, 'c');
440 continue;
441 }
442 // Stop with signal and thread info
443 state = eStateStopped;
444 break;
445
446 case 'W':
447 case 'X':
448 // process exited
449 state = eStateExited;
450 break;
451
452 case 'O':
453 // STDOUT
454 {
455 std::string inferior_stdout;
456 inferior_stdout.reserve(response.GetBytesLeft () / 2);
457 char ch;
458 while ((ch = response.GetHexU8()) != '\0')
459 inferior_stdout.append(1, ch);
460 process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
461 }
462 break;
463
464 case 'E':
465 // ERROR
466 state = eStateInvalid;
467 break;
468
469 default:
470 if (log)
471 log->Printf ("GDBRemoteCommunicationClient::%s () unrecognized async packet", __FUNCTION__);
472 state = eStateInvalid;
473 break;
474 }
475 }
476 }
477 else
478 {
479 if (log)
480 log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(...) => false", __FUNCTION__);
481 state = eStateInvalid;
482 }
483 }
484 if (log)
485 log->Printf ("GDBRemoteCommunicationClient::%s () => %s", __FUNCTION__, StateAsCString(state));
486 response.SetFilePos(0);
487 m_private_is_running.SetValue (false, eBroadcastAlways);
488 m_public_is_running.SetValue (false, eBroadcastAlways);
489 return state;
490}
491
492bool
493GDBRemoteCommunicationClient::SendAsyncSignal (int signo)
494{
495 m_async_signal = signo;
496 bool timed_out = false;
497 bool sent_interrupt = false;
498 Mutex::Locker locker;
499 if (SendInterrupt (locker, 1, sent_interrupt, timed_out))
500 return true;
501 m_async_signal = -1;
502 return false;
503}
504
505// This function takes a mutex locker as a parameter in case the GetSequenceMutex
506// actually succeeds. If it doesn't succeed in acquiring the sequence mutex
507// (the expected result), then it will send the halt packet. If it does succeed
508// then the caller that requested the interrupt will want to keep the sequence
509// locked down so that no one else can send packets while the caller has control.
510// This function usually gets called when we are running and need to stop the
511// target. It can also be used when we are running and and we need to do something
512// else (like read/write memory), so we need to interrupt the running process
513// (gdb remote protocol requires this), and do what we need to do, then resume.
514
515bool
516GDBRemoteCommunicationClient::SendInterrupt
517(
518 Mutex::Locker& locker,
519 uint32_t seconds_to_wait_for_stop,
520 bool &sent_interrupt,
521 bool &timed_out
522)
523{
524 sent_interrupt = false;
525 timed_out = false;
526 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
527
528 if (IsRunning())
529 {
530 // Only send an interrupt if our debugserver is running...
531 if (GetSequenceMutex (locker) == false)
532 {
533 // Someone has the mutex locked waiting for a response or for the
534 // inferior to stop, so send the interrupt on the down low...
535 char ctrl_c = '\x03';
536 ConnectionStatus status = eConnectionStatusSuccess;
537 TimeValue timeout;
538 if (seconds_to_wait_for_stop)
539 {
540 timeout = TimeValue::Now();
541 timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
542 }
543 size_t bytes_written = Write (&ctrl_c, 1, status, NULL);
544 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_PROCESS, "send packet: \\x03");
545 if (bytes_written > 0)
546 {
547 sent_interrupt = true;
548 if (seconds_to_wait_for_stop)
549 {
550 if (m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out))
551 {
552 if (log)
553 log->Printf ("GDBRemoteCommunicationClient::%s () - sent interrupt, private state stopped", __FUNCTION__);
554 return true;
555 }
556 else
557 {
558 if (log)
559 log->Printf ("GDBRemoteCommunicationClient::%s () - sent interrupt, timed out wating for async thread resume", __FUNCTION__);
560 }
561 }
562 else
563 {
564 if (log)
565 log->Printf ("GDBRemoteCommunicationClient::%s () - sent interrupt, not waiting for stop...", __FUNCTION__);
566 return true;
567 }
568 }
569 else
570 {
571 if (log)
572 log->Printf ("GDBRemoteCommunicationClient::%s () - failed to write interrupt", __FUNCTION__);
573 }
574 return false;
575 }
576 else
577 {
578 if (log)
579 log->Printf ("GDBRemoteCommunicationClient::%s () - got sequence mutex without having to interrupt", __FUNCTION__);
580 }
581 }
582 return true;
583}
584
585lldb::pid_t
586GDBRemoteCommunicationClient::GetCurrentProcessID ()
587{
588 StringExtractorGDBRemote response;
589 if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false))
590 {
591 if (response.GetChar() == 'Q')
592 if (response.GetChar() == 'C')
593 return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
594 }
595 return LLDB_INVALID_PROCESS_ID;
596}
597
598bool
599GDBRemoteCommunicationClient::GetLaunchSuccess (std::string &error_str)
600{
601 error_str.clear();
602 StringExtractorGDBRemote response;
603 if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, false))
604 {
605 if (response.IsOKResponse())
606 return true;
607 if (response.GetChar() == 'E')
608 {
609 // A string the describes what failed when launching...
610 error_str = response.GetStringRef().substr(1);
611 }
612 else
613 {
614 error_str.assign ("unknown error occurred launching process");
615 }
616 }
617 else
618 {
619 error_str.assign ("failed to send the qLaunchSuccess packet");
620 }
621 return false;
622}
623
624int
625GDBRemoteCommunicationClient::SendArgumentsPacket (char const *argv[])
626{
627 if (argv && argv[0])
628 {
629 StreamString packet;
630 packet.PutChar('A');
631 const char *arg;
632 for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
633 {
634 const int arg_len = strlen(arg);
635 if (i > 0)
636 packet.PutChar(',');
637 packet.Printf("%i,%i,", arg_len * 2, i);
638 packet.PutBytesAsRawHex8 (arg, arg_len);
639 }
640
641 StringExtractorGDBRemote response;
642 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
643 {
644 if (response.IsOKResponse())
645 return 0;
646 uint8_t error = response.GetError();
647 if (error)
648 return error;
649 }
650 }
651 return -1;
652}
653
654int
655GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_value)
656{
657 if (name_equal_value && name_equal_value[0])
658 {
659 StreamString packet;
660 packet.Printf("QEnvironment:%s", name_equal_value);
661 StringExtractorGDBRemote response;
662 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
663 {
664 if (response.IsOKResponse())
665 return 0;
666 uint8_t error = response.GetError();
667 if (error)
668 return error;
669 }
670 }
671 return -1;
672}
673
674bool
675GDBRemoteCommunicationClient::GetHostInfo ()
676{
677 if (m_supports_qHostInfo == eLazyBoolCalculate)
678 {
679 m_supports_qHostInfo = eLazyBoolNo;
680
681 StringExtractorGDBRemote response;
682 if (SendPacketAndWaitForResponse ("qHostInfo", response, false))
683 {
684 if (response.IsUnsupportedResponse())
685 return false;
686
687 m_supports_qHostInfo = eLazyBoolYes;
688
689 std::string name;
690 std::string value;
691 uint32_t cpu = LLDB_INVALID_CPUTYPE;
692 uint32_t sub = 0;
693
694 while (response.GetNameColonValue(name, value))
695 {
696 if (name.compare("cputype") == 0)
697 {
698 // exception type in big endian hex
699 cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
700 }
701 else if (name.compare("cpusubtype") == 0)
702 {
703 // exception count in big endian hex
704 sub = Args::StringToUInt32 (value.c_str(), 0, 0);
705 }
706 else if (name.compare("ostype") == 0)
707 {
708 // exception data in big endian hex
709 m_os.SetCString(value.c_str());
710 }
711 else if (name.compare("vendor") == 0)
712 {
713 m_vendor.SetCString(value.c_str());
714 }
715 else if (name.compare("endian") == 0)
716 {
717 if (value.compare("little") == 0)
718 m_byte_order = eByteOrderLittle;
719 else if (value.compare("big") == 0)
720 m_byte_order = eByteOrderBig;
721 else if (value.compare("pdp") == 0)
722 m_byte_order = eByteOrderPDP;
723 }
724 else if (name.compare("ptrsize") == 0)
725 {
726 m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
727 }
728 }
729
730 if (cpu != LLDB_INVALID_CPUTYPE)
731 m_arch.SetArchitecture (lldb::eArchTypeMachO, cpu, sub);
732 }
733 }
734 return m_supports_qHostInfo == eLazyBoolYes;
735}
736
737int
738GDBRemoteCommunicationClient::SendAttach
739(
740 lldb::pid_t pid,
741 StringExtractorGDBRemote& response
742)
743{
744 if (pid != LLDB_INVALID_PROCESS_ID)
745 {
746 StreamString packet;
747 packet.Printf("vAttach;%x", pid);
748
749 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
750 {
751 if (response.IsErrorResponse())
752 return response.GetError();
753 return 0;
754 }
755 }
756 return -1;
757}
758
759const lldb_private::ArchSpec &
760GDBRemoteCommunicationClient::GetHostArchitecture ()
761{
762 if (!HostInfoIsValid ())
763 GetHostInfo ();
764 return m_arch;
765}
766
767const lldb_private::ConstString &
768GDBRemoteCommunicationClient::GetOSString ()
769{
770 if (!HostInfoIsValid ())
771 GetHostInfo ();
772 return m_os;
773}
774
775const lldb_private::ConstString &
776GDBRemoteCommunicationClient::GetVendorString()
777{
778 if (!HostInfoIsValid ())
779 GetHostInfo ();
780 return m_vendor;
781}
782
783lldb::ByteOrder
784GDBRemoteCommunicationClient::GetByteOrder ()
785{
786 if (!HostInfoIsValid ())
787 GetHostInfo ();
788 return m_byte_order;
789}
790
791uint32_t
792GDBRemoteCommunicationClient::GetAddressByteSize ()
793{
794 if (!HostInfoIsValid ())
795 GetHostInfo ();
796 return m_pointer_byte_size;
797}
798
799addr_t
800GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
801{
802 char packet[64];
803 ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
804 permissions & lldb::ePermissionsReadable ? "r" : "",
805 permissions & lldb::ePermissionsWritable ? "w" : "",
806 permissions & lldb::ePermissionsExecutable ? "x" : "");
807 StringExtractorGDBRemote response;
808 if (SendPacketAndWaitForResponse (packet, response, false))
809 {
810 if (!response.IsErrorResponse())
811 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
812 }
813 return LLDB_INVALID_ADDRESS;
814}
815
816bool
817GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
818{
819 char packet[64];
820 snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
821 StringExtractorGDBRemote response;
822 if (SendPacketAndWaitForResponse (packet, response, false))
823 {
824 if (response.IsOKResponse())
825 return true;
826 }
827 return false;
828}
829
830int
831GDBRemoteCommunicationClient::SetSTDIN (char const *path)
832{
833 if (path && path[0])
834 {
835 StreamString packet;
836 packet.PutCString("QSetSTDIN:");
837 packet.PutBytesAsRawHex8(path, strlen(path));
838
839 StringExtractorGDBRemote response;
840 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
841 {
842 if (response.IsOKResponse())
843 return 0;
844 uint8_t error = response.GetError();
845 if (error)
846 return error;
847 }
848 }
849 return -1;
850}
851
852int
853GDBRemoteCommunicationClient::SetSTDOUT (char const *path)
854{
855 if (path && path[0])
856 {
857 StreamString packet;
858 packet.PutCString("QSetSTDOUT:");
859 packet.PutBytesAsRawHex8(path, strlen(path));
860
861 StringExtractorGDBRemote response;
862 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
863 {
864 if (response.IsOKResponse())
865 return 0;
866 uint8_t error = response.GetError();
867 if (error)
868 return error;
869 }
870 }
871 return -1;
872}
873
874int
875GDBRemoteCommunicationClient::SetSTDERR (char const *path)
876{
877 if (path && path[0])
878 {
879 StreamString packet;
880 packet.PutCString("QSetSTDERR:");
881 packet.PutBytesAsRawHex8(path, strlen(path));
882
883 StringExtractorGDBRemote response;
884 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
885 {
886 if (response.IsOKResponse())
887 return 0;
888 uint8_t error = response.GetError();
889 if (error)
890 return error;
891 }
892 }
893 return -1;
894}
895
896int
897GDBRemoteCommunicationClient::SetWorkingDir (char const *path)
898{
899 if (path && path[0])
900 {
901 StreamString packet;
902 packet.PutCString("QSetWorkingDir:");
903 packet.PutBytesAsRawHex8(path, strlen(path));
904
905 StringExtractorGDBRemote response;
906 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
907 {
908 if (response.IsOKResponse())
909 return 0;
910 uint8_t error = response.GetError();
911 if (error)
912 return error;
913 }
914 }
915 return -1;
916}
917
918int
919GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
920{
921 StreamString packet;
922 packet.Printf("QSetDisableASLR:%i", enable ? 1 : 0);
923
924 StringExtractorGDBRemote response;
925 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
926 {
927 if (response.IsOKResponse())
928 return 0;
929 uint8_t error = response.GetError();
930 if (error)
931 return error;
932 }
933 return -1;
934}