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