blob: f8a0600fb81c17a66d6f5424cd939cd3b2b5f018 [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 Clayton58e26e02011-03-24 04:28:38 +000053 m_host_arch(),
54 m_os_version_major (UINT32_MAX),
55 m_os_version_minor (UINT32_MAX),
56 m_os_version_update (UINT32_MAX)
Greg Clayton61d043b2011-03-22 04:00:09 +000057{
58 m_rx_packet_listener.StartListeningForEvents(this,
59 Communication::eBroadcastBitPacketAvailable |
60 Communication::eBroadcastBitReadThreadDidExit);
61}
62
63//----------------------------------------------------------------------
64// Destructor
65//----------------------------------------------------------------------
66GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient()
67{
68 m_rx_packet_listener.StopListeningForEvents(this,
69 Communication::eBroadcastBitPacketAvailable |
70 Communication::eBroadcastBitReadThreadDidExit);
71 if (IsConnected())
72 {
73 StopReadThread();
74 Disconnect();
75 }
76}
77
78bool
Greg Clayton58e26e02011-03-24 04:28:38 +000079GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
80{
81 // Start the read thread after we send the handshake ack since if we
82 // fail to send the handshake ack, there is no reason to continue...
83 if (SendAck())
84 return StartReadThread (error_ptr);
85
86 if (error_ptr)
87 error_ptr->SetErrorString("failed to send the handshake ack");
88 return false;
89}
90
91void
92GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
Greg Clayton61d043b2011-03-22 04:00:09 +000093{
94 if (m_supports_not_sending_acks == eLazyBoolCalculate)
95 {
Greg Clayton58e26e02011-03-24 04:28:38 +000096 m_send_acks = true;
Greg Clayton61d043b2011-03-22 04:00:09 +000097 m_supports_not_sending_acks = eLazyBoolNo;
Greg Clayton58e26e02011-03-24 04:28:38 +000098
99 StringExtractorGDBRemote response;
Greg Clayton61d043b2011-03-22 04:00:09 +0000100 if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false))
101 {
102 if (response.IsOKResponse())
Greg Clayton58e26e02011-03-24 04:28:38 +0000103 {
104 m_send_acks = false;
Greg Clayton61d043b2011-03-22 04:00:09 +0000105 m_supports_not_sending_acks = eLazyBoolYes;
Greg Clayton58e26e02011-03-24 04:28:38 +0000106 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000107 }
108 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000109}
110
111void
112GDBRemoteCommunicationClient::ResetDiscoverableSettings()
113{
114 m_supports_not_sending_acks = eLazyBoolCalculate;
115 m_supports_thread_suffix = eLazyBoolCalculate;
116 m_supports_qHostInfo = eLazyBoolCalculate;
117 m_supports_vCont_c = eLazyBoolCalculate;
118 m_supports_vCont_C = eLazyBoolCalculate;
119 m_supports_vCont_s = eLazyBoolCalculate;
120 m_supports_vCont_S = eLazyBoolCalculate;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000121 m_host_arch.Clear();
Greg Clayton61d043b2011-03-22 04:00:09 +0000122}
123
124
125bool
126GDBRemoteCommunicationClient::GetThreadSuffixSupported ()
127{
128 if (m_supports_thread_suffix == eLazyBoolCalculate)
129 {
130 StringExtractorGDBRemote response;
131 m_supports_thread_suffix = eLazyBoolNo;
132 if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false))
133 {
134 if (response.IsOKResponse())
135 m_supports_thread_suffix = eLazyBoolYes;
136 }
137 }
138 return m_supports_thread_suffix;
139}
140bool
141GDBRemoteCommunicationClient::GetVContSupported (char flavor)
142{
143 if (m_supports_vCont_c == eLazyBoolCalculate)
144 {
145 StringExtractorGDBRemote response;
146 m_supports_vCont_any = eLazyBoolNo;
147 m_supports_vCont_all = eLazyBoolNo;
148 m_supports_vCont_c = eLazyBoolNo;
149 m_supports_vCont_C = eLazyBoolNo;
150 m_supports_vCont_s = eLazyBoolNo;
151 m_supports_vCont_S = eLazyBoolNo;
152 if (SendPacketAndWaitForResponse("vCont?", response, false))
153 {
154 const char *response_cstr = response.GetStringRef().c_str();
155 if (::strstr (response_cstr, ";c"))
156 m_supports_vCont_c = eLazyBoolYes;
157
158 if (::strstr (response_cstr, ";C"))
159 m_supports_vCont_C = eLazyBoolYes;
160
161 if (::strstr (response_cstr, ";s"))
162 m_supports_vCont_s = eLazyBoolYes;
163
164 if (::strstr (response_cstr, ";S"))
165 m_supports_vCont_S = eLazyBoolYes;
166
167 if (m_supports_vCont_c == eLazyBoolYes &&
168 m_supports_vCont_C == eLazyBoolYes &&
169 m_supports_vCont_s == eLazyBoolYes &&
170 m_supports_vCont_S == eLazyBoolYes)
171 {
172 m_supports_vCont_all = eLazyBoolYes;
173 }
174
175 if (m_supports_vCont_c == eLazyBoolYes ||
176 m_supports_vCont_C == eLazyBoolYes ||
177 m_supports_vCont_s == eLazyBoolYes ||
178 m_supports_vCont_S == eLazyBoolYes)
179 {
180 m_supports_vCont_any = eLazyBoolYes;
181 }
182 }
183 }
184
185 switch (flavor)
186 {
187 case 'a': return m_supports_vCont_any;
188 case 'A': return m_supports_vCont_all;
189 case 'c': return m_supports_vCont_c;
190 case 'C': return m_supports_vCont_C;
191 case 's': return m_supports_vCont_s;
192 case 'S': return m_supports_vCont_S;
193 default: break;
194 }
195 return false;
196}
197
198
199size_t
200GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
201(
202 const char *payload,
203 StringExtractorGDBRemote &response,
204 bool send_async
205)
206{
207 return SendPacketAndWaitForResponse (payload,
208 ::strlen (payload),
209 response,
210 send_async);
211}
212
213size_t
214GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
215(
216 const char *payload,
217 size_t payload_length,
218 StringExtractorGDBRemote &response,
219 bool send_async
220)
221{
222 Mutex::Locker locker;
223 TimeValue timeout_time;
224 timeout_time = TimeValue::Now();
225 timeout_time.OffsetWithSeconds (m_packet_timeout);
226 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
227
228 if (GetSequenceMutex (locker))
229 {
230 if (SendPacketNoLock (payload, strlen(payload)))
231 return WaitForPacketNoLock (response, &timeout_time);
232 }
233 else
234 {
235 if (send_async)
236 {
237 Mutex::Locker async_locker (m_async_mutex);
238 m_async_packet.assign(payload, payload_length);
239 m_async_packet_predicate.SetValue (true, eBroadcastNever);
240
241 if (log)
242 log->Printf ("async: async packet = %s", m_async_packet.c_str());
243
244 bool timed_out = false;
245 bool sent_interrupt = false;
246 if (SendInterrupt(locker, 2, sent_interrupt, timed_out))
247 {
248 if (sent_interrupt)
249 {
250 if (log)
251 log->Printf ("async: sent interrupt");
252 if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
253 {
254 if (log)
255 log->Printf ("async: got response");
256 response = m_async_response;
257 return response.GetStringRef().size();
258 }
259 else
260 {
261 if (log)
262 log->Printf ("async: timed out waiting for response");
263 }
264
265 // Make sure we wait until the continue packet has been sent again...
266 if (m_private_is_running.WaitForValueEqualTo (true, &timeout_time, &timed_out))
267 {
268 if (log)
269 log->Printf ("async: timed out waiting for process to resume");
270 }
271 }
272 else
273 {
274 // We had a racy condition where we went to send the interrupt
275 // yet we were able to get the loc
276 }
277 }
278 else
279 {
280 if (log)
281 log->Printf ("async: failed to interrupt");
282 }
283 }
284 else
285 {
286 if (log)
287 log->Printf ("mutex taken and send_async == false, aborting packet");
288 }
289 }
290 return 0;
291}
292
293//template<typename _Tp>
294//class ScopedValueChanger
295//{
296//public:
297// // Take a value reference and the value to assign it to when this class
298// // instance goes out of scope.
299// ScopedValueChanger (_Tp &value_ref, _Tp value) :
300// m_value_ref (value_ref),
301// m_value (value)
302// {
303// }
304//
305// // This object is going out of scope, change the value pointed to by
306// // m_value_ref to the value we got during construction which was stored in
307// // m_value;
308// ~ScopedValueChanger ()
309// {
310// m_value_ref = m_value;
311// }
312//protected:
313// _Tp &m_value_ref; // A reference to the value we will change when this object destructs
314// _Tp m_value; // The value to assign to m_value_ref when this goes out of scope.
315//};
316
317StateType
318GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
319(
320 ProcessGDBRemote *process,
321 const char *payload,
322 size_t packet_length,
323 StringExtractorGDBRemote &response
324)
325{
326 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
327 if (log)
328 log->Printf ("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
329
330 Mutex::Locker locker(m_sequence_mutex);
331 StateType state = eStateRunning;
332
333 BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
334 m_public_is_running.SetValue (true, eBroadcastNever);
335 // Set the starting continue packet into "continue_packet". This packet
336 // make change if we are interrupted and we continue after an async packet...
337 std::string continue_packet(payload, packet_length);
338
339 while (state == eStateRunning)
340 {
341 if (log)
342 log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
343 if (SendPacket(continue_packet.c_str(), continue_packet.size()) == 0)
344 state = eStateInvalid;
345
346 m_private_is_running.SetValue (true, eBroadcastNever);
347
348 if (log)
349 log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%.*s)", __FUNCTION__);
350
351 if (WaitForPacket (response, (TimeValue*)NULL))
352 {
353 if (response.Empty())
354 state = eStateInvalid;
355 else
356 {
357 const char stop_type = response.GetChar();
358 if (log)
359 log->Printf ("GDBRemoteCommunicationClient::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str());
360 switch (stop_type)
361 {
362 case 'T':
363 case 'S':
364 if (process->GetStopID() == 0)
365 {
366 if (process->GetID() == LLDB_INVALID_PROCESS_ID)
367 {
368 lldb::pid_t pid = GetCurrentProcessID ();
369 if (pid != LLDB_INVALID_PROCESS_ID)
370 process->SetID (pid);
371 }
372 process->BuildDynamicRegisterInfo (true);
373 }
374
375 // Privately notify any internal threads that we have stopped
376 // in case we wanted to interrupt our process, yet we might
377 // send a packet and continue without returning control to the
378 // user.
379 m_private_is_running.SetValue (false, eBroadcastAlways);
380 if (m_async_signal != -1)
381 {
382 if (log)
383 log->Printf ("async: send signo = %s", Host::GetSignalAsCString (m_async_signal));
384
385 // Save off the async signal we are supposed to send
386 const int async_signal = m_async_signal;
387 // Clear the async signal member so we don't end up
388 // sending the signal multiple times...
389 m_async_signal = -1;
390 // Check which signal we stopped with
391 uint8_t signo = response.GetHexU8(255);
392 if (signo == async_signal)
393 {
394 if (log)
395 log->Printf ("async: stopped with signal %s, we are done running", Host::GetSignalAsCString (signo));
396
397 // We already stopped with a signal that we wanted
398 // to stop with, so we are done
399 response.SetFilePos (0);
400 }
401 else
402 {
403 // We stopped with a different signal that the one
404 // we wanted to stop with, so now we must resume
405 // with the signal we want
406 char signal_packet[32];
407 int signal_packet_len = 0;
408 signal_packet_len = ::snprintf (signal_packet,
409 sizeof (signal_packet),
410 "C%2.2x",
411 async_signal);
412
413 if (log)
414 log->Printf ("async: stopped with signal %s, resume with %s",
415 Host::GetSignalAsCString (signo),
416 Host::GetSignalAsCString (async_signal));
417
418 // Set the continue packet to resume...
419 continue_packet.assign(signal_packet, signal_packet_len);
420 continue;
421 }
422 }
423 else if (m_async_packet_predicate.GetValue())
424 {
425 // We are supposed to send an asynchronous packet while
426 // we are running.
427 m_async_response.Clear();
428 if (m_async_packet.empty())
429 {
430 if (log)
431 log->Printf ("async: error: empty async packet");
432
433 }
434 else
435 {
436 if (log)
437 log->Printf ("async: sending packet: %s",
438 m_async_packet.c_str());
439
440 SendPacketAndWaitForResponse (&m_async_packet[0],
441 m_async_packet.size(),
442 m_async_response,
443 false);
444 }
445 // Let the other thread that was trying to send the async
446 // packet know that the packet has been sent and response is
447 // ready...
448 m_async_packet_predicate.SetValue(false, eBroadcastAlways);
449
450 // Set the continue packet to resume...
451 continue_packet.assign (1, 'c');
452 continue;
453 }
454 // Stop with signal and thread info
455 state = eStateStopped;
456 break;
457
458 case 'W':
459 case 'X':
460 // process exited
461 state = eStateExited;
462 break;
463
464 case 'O':
465 // STDOUT
466 {
467 std::string inferior_stdout;
468 inferior_stdout.reserve(response.GetBytesLeft () / 2);
469 char ch;
470 while ((ch = response.GetHexU8()) != '\0')
471 inferior_stdout.append(1, ch);
472 process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
473 }
474 break;
475
476 case 'E':
477 // ERROR
478 state = eStateInvalid;
479 break;
480
481 default:
482 if (log)
483 log->Printf ("GDBRemoteCommunicationClient::%s () unrecognized async packet", __FUNCTION__);
484 state = eStateInvalid;
485 break;
486 }
487 }
488 }
489 else
490 {
491 if (log)
492 log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(...) => false", __FUNCTION__);
493 state = eStateInvalid;
494 }
495 }
496 if (log)
497 log->Printf ("GDBRemoteCommunicationClient::%s () => %s", __FUNCTION__, StateAsCString(state));
498 response.SetFilePos(0);
499 m_private_is_running.SetValue (false, eBroadcastAlways);
500 m_public_is_running.SetValue (false, eBroadcastAlways);
501 return state;
502}
503
504bool
505GDBRemoteCommunicationClient::SendAsyncSignal (int signo)
506{
507 m_async_signal = signo;
508 bool timed_out = false;
509 bool sent_interrupt = false;
510 Mutex::Locker locker;
511 if (SendInterrupt (locker, 1, sent_interrupt, timed_out))
512 return true;
513 m_async_signal = -1;
514 return false;
515}
516
517// This function takes a mutex locker as a parameter in case the GetSequenceMutex
518// actually succeeds. If it doesn't succeed in acquiring the sequence mutex
519// (the expected result), then it will send the halt packet. If it does succeed
520// then the caller that requested the interrupt will want to keep the sequence
521// locked down so that no one else can send packets while the caller has control.
522// This function usually gets called when we are running and need to stop the
523// target. It can also be used when we are running and and we need to do something
524// else (like read/write memory), so we need to interrupt the running process
525// (gdb remote protocol requires this), and do what we need to do, then resume.
526
527bool
528GDBRemoteCommunicationClient::SendInterrupt
529(
530 Mutex::Locker& locker,
531 uint32_t seconds_to_wait_for_stop,
532 bool &sent_interrupt,
533 bool &timed_out
534)
535{
536 sent_interrupt = false;
537 timed_out = false;
538 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
539
540 if (IsRunning())
541 {
542 // Only send an interrupt if our debugserver is running...
543 if (GetSequenceMutex (locker) == false)
544 {
545 // Someone has the mutex locked waiting for a response or for the
546 // inferior to stop, so send the interrupt on the down low...
547 char ctrl_c = '\x03';
548 ConnectionStatus status = eConnectionStatusSuccess;
549 TimeValue timeout;
550 if (seconds_to_wait_for_stop)
551 {
552 timeout = TimeValue::Now();
553 timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
554 }
555 size_t bytes_written = Write (&ctrl_c, 1, status, NULL);
556 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_PROCESS, "send packet: \\x03");
557 if (bytes_written > 0)
558 {
559 sent_interrupt = true;
560 if (seconds_to_wait_for_stop)
561 {
562 if (m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out))
563 {
564 if (log)
565 log->Printf ("GDBRemoteCommunicationClient::%s () - sent interrupt, private state stopped", __FUNCTION__);
566 return true;
567 }
568 else
569 {
570 if (log)
571 log->Printf ("GDBRemoteCommunicationClient::%s () - sent interrupt, timed out wating for async thread resume", __FUNCTION__);
572 }
573 }
574 else
575 {
576 if (log)
577 log->Printf ("GDBRemoteCommunicationClient::%s () - sent interrupt, not waiting for stop...", __FUNCTION__);
578 return true;
579 }
580 }
581 else
582 {
583 if (log)
584 log->Printf ("GDBRemoteCommunicationClient::%s () - failed to write interrupt", __FUNCTION__);
585 }
586 return false;
587 }
588 else
589 {
590 if (log)
591 log->Printf ("GDBRemoteCommunicationClient::%s () - got sequence mutex without having to interrupt", __FUNCTION__);
592 }
593 }
594 return true;
595}
596
597lldb::pid_t
598GDBRemoteCommunicationClient::GetCurrentProcessID ()
599{
600 StringExtractorGDBRemote response;
601 if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false))
602 {
603 if (response.GetChar() == 'Q')
604 if (response.GetChar() == 'C')
605 return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
606 }
607 return LLDB_INVALID_PROCESS_ID;
608}
609
610bool
611GDBRemoteCommunicationClient::GetLaunchSuccess (std::string &error_str)
612{
613 error_str.clear();
614 StringExtractorGDBRemote response;
615 if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, false))
616 {
617 if (response.IsOKResponse())
618 return true;
619 if (response.GetChar() == 'E')
620 {
621 // A string the describes what failed when launching...
622 error_str = response.GetStringRef().substr(1);
623 }
624 else
625 {
626 error_str.assign ("unknown error occurred launching process");
627 }
628 }
629 else
630 {
631 error_str.assign ("failed to send the qLaunchSuccess packet");
632 }
633 return false;
634}
635
636int
637GDBRemoteCommunicationClient::SendArgumentsPacket (char const *argv[])
638{
639 if (argv && argv[0])
640 {
641 StreamString packet;
642 packet.PutChar('A');
643 const char *arg;
644 for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
645 {
646 const int arg_len = strlen(arg);
647 if (i > 0)
648 packet.PutChar(',');
649 packet.Printf("%i,%i,", arg_len * 2, i);
650 packet.PutBytesAsRawHex8 (arg, arg_len);
651 }
652
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
666int
667GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_value)
668{
669 if (name_equal_value && name_equal_value[0])
670 {
671 StreamString packet;
672 packet.Printf("QEnvironment:%s", name_equal_value);
673 StringExtractorGDBRemote response;
674 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
675 {
676 if (response.IsOKResponse())
677 return 0;
678 uint8_t error = response.GetError();
679 if (error)
680 return error;
681 }
682 }
683 return -1;
684}
685
686bool
Greg Clayton58e26e02011-03-24 04:28:38 +0000687GDBRemoteCommunicationClient::GetOSVersion (uint32_t &major,
688 uint32_t &minor,
689 uint32_t &update)
690{
691 if (GetHostInfo ())
692 {
693 if (m_os_version_major != UINT32_MAX)
694 {
695 major = m_os_version_major;
696 minor = m_os_version_minor;
697 update = m_os_version_update;
698 return true;
699 }
700 }
701 return false;
702}
703
704bool
705GDBRemoteCommunicationClient::GetOSBuildString (std::string &s)
706{
707 if (GetHostInfo ())
708 {
709 if (!m_os_build.empty())
710 {
711 s = m_os_build;
712 return true;
713 }
714 }
715 s.clear();
716 return false;
717}
718
719
720bool
721GDBRemoteCommunicationClient::GetOSKernelDescription (std::string &s)
722{
723 if (GetHostInfo ())
724 {
725 if (!m_os_kernel.empty())
726 {
727 s = m_os_kernel;
728 return true;
729 }
730 }
731 s.clear();
732 return false;
733}
734
735bool
736GDBRemoteCommunicationClient::GetHostname (std::string &s)
737{
738 if (GetHostInfo ())
739 {
740 if (!m_hostname.empty())
741 {
742 s = m_hostname;
743 return true;
744 }
745 }
746 s.clear();
747 return false;
748}
749
750ArchSpec
751GDBRemoteCommunicationClient::GetSystemArchitecture ()
752{
753 if (GetHostInfo ())
754 return m_host_arch;
755 return ArchSpec();
756}
757
758
759bool
Greg Clayton61d043b2011-03-22 04:00:09 +0000760GDBRemoteCommunicationClient::GetHostInfo ()
761{
762 if (m_supports_qHostInfo == eLazyBoolCalculate)
763 {
764 m_supports_qHostInfo = eLazyBoolNo;
765
766 StringExtractorGDBRemote response;
767 if (SendPacketAndWaitForResponse ("qHostInfo", response, false))
768 {
769 if (response.IsUnsupportedResponse())
770 return false;
771
772 m_supports_qHostInfo = eLazyBoolYes;
773
774 std::string name;
775 std::string value;
776 uint32_t cpu = LLDB_INVALID_CPUTYPE;
777 uint32_t sub = 0;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000778 std::string arch_name;
779 std::string os_name;
780 std::string vendor_name;
Greg Clayton58e26e02011-03-24 04:28:38 +0000781 std::string triple;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000782 uint32_t pointer_byte_size = 0;
Greg Clayton58e26e02011-03-24 04:28:38 +0000783 StringExtractor extractor;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000784 ByteOrder byte_order = eByteOrderInvalid;
Greg Clayton61d043b2011-03-22 04:00:09 +0000785 while (response.GetNameColonValue(name, value))
786 {
787 if (name.compare("cputype") == 0)
788 {
789 // exception type in big endian hex
790 cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
791 }
792 else if (name.compare("cpusubtype") == 0)
793 {
794 // exception count in big endian hex
795 sub = Args::StringToUInt32 (value.c_str(), 0, 0);
796 }
Greg Claytoncb8977d2011-03-23 00:09:55 +0000797 else if (name.compare("arch") == 0)
798 {
799 arch_name.swap (value);
800 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000801 else if (name.compare("triple") == 0)
802 {
803 // The triple comes as ASCII hex bytes since it contains '-' chars
804 extractor.GetStringRef().swap(value);
805 extractor.SetFilePos(0);
806 extractor.GetHexByteString (triple);
807 }
808 else if (name.compare("os_build") == 0)
809 {
810 extractor.GetStringRef().swap(value);
811 extractor.SetFilePos(0);
812 extractor.GetHexByteString (m_os_build);
813 }
814 else if (name.compare("hostname") == 0)
815 {
816 extractor.GetStringRef().swap(value);
817 extractor.SetFilePos(0);
818 extractor.GetHexByteString (m_hostname);
819 }
820 else if (name.compare("os_kernel") == 0)
821 {
822 extractor.GetStringRef().swap(value);
823 extractor.SetFilePos(0);
824 extractor.GetHexByteString (m_os_kernel);
825 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000826 else if (name.compare("ostype") == 0)
827 {
Greg Claytoncb8977d2011-03-23 00:09:55 +0000828 os_name.swap (value);
Greg Clayton61d043b2011-03-22 04:00:09 +0000829 }
830 else if (name.compare("vendor") == 0)
831 {
Greg Claytoncb8977d2011-03-23 00:09:55 +0000832 vendor_name.swap(value);
Greg Clayton61d043b2011-03-22 04:00:09 +0000833 }
834 else if (name.compare("endian") == 0)
835 {
836 if (value.compare("little") == 0)
Greg Claytoncb8977d2011-03-23 00:09:55 +0000837 byte_order = eByteOrderLittle;
Greg Clayton61d043b2011-03-22 04:00:09 +0000838 else if (value.compare("big") == 0)
Greg Claytoncb8977d2011-03-23 00:09:55 +0000839 byte_order = eByteOrderBig;
Greg Clayton61d043b2011-03-22 04:00:09 +0000840 else if (value.compare("pdp") == 0)
Greg Claytoncb8977d2011-03-23 00:09:55 +0000841 byte_order = eByteOrderPDP;
Greg Clayton61d043b2011-03-22 04:00:09 +0000842 }
843 else if (name.compare("ptrsize") == 0)
844 {
Greg Claytoncb8977d2011-03-23 00:09:55 +0000845 pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
Greg Clayton61d043b2011-03-22 04:00:09 +0000846 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000847 else if (name.compare("os_version") == 0)
848 {
849 Args::StringToVersion (value.c_str(),
850 m_os_version_major,
851 m_os_version_minor,
852 m_os_version_update);
853 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000854 }
855
Greg Clayton58e26e02011-03-24 04:28:38 +0000856 if (triple.empty())
Greg Claytoncb8977d2011-03-23 00:09:55 +0000857 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000858 if (arch_name.empty())
Greg Claytoncb8977d2011-03-23 00:09:55 +0000859 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000860 if (cpu != LLDB_INVALID_CPUTYPE)
861 {
Greg Claytonb3448432011-03-24 21:19:54 +0000862 m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
Greg Clayton58e26e02011-03-24 04:28:38 +0000863 if (pointer_byte_size)
864 {
865 assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
866 }
867 if (byte_order != eByteOrderInvalid)
868 {
869 assert (byte_order == m_host_arch.GetByteOrder());
870 }
871 if (!vendor_name.empty())
872 m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
873 if (!os_name.empty())
874 m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name));
875
876 }
877 }
878 else
879 {
880 std::string triple;
881 triple += arch_name;
882 triple += '-';
883 if (vendor_name.empty())
884 triple += "unknown";
885 else
886 triple += vendor_name;
887 triple += '-';
888 if (os_name.empty())
889 triple += "unknown";
890 else
891 triple += os_name;
892 m_host_arch.SetTriple (triple.c_str());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000893 if (pointer_byte_size)
894 {
895 assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
896 }
897 if (byte_order != eByteOrderInvalid)
898 {
899 assert (byte_order == m_host_arch.GetByteOrder());
900 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000901
Greg Claytoncb8977d2011-03-23 00:09:55 +0000902 }
903 }
904 else
905 {
Greg Claytoncb8977d2011-03-23 00:09:55 +0000906 m_host_arch.SetTriple (triple.c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000907 if (pointer_byte_size)
908 {
909 assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
910 }
911 if (byte_order != eByteOrderInvalid)
912 {
913 assert (byte_order == m_host_arch.GetByteOrder());
914 }
915 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000916 }
917 }
918 return m_supports_qHostInfo == eLazyBoolYes;
919}
920
921int
922GDBRemoteCommunicationClient::SendAttach
923(
924 lldb::pid_t pid,
925 StringExtractorGDBRemote& response
926)
927{
928 if (pid != LLDB_INVALID_PROCESS_ID)
929 {
930 StreamString packet;
931 packet.Printf("vAttach;%x", pid);
932
933 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
934 {
935 if (response.IsErrorResponse())
936 return response.GetError();
937 return 0;
938 }
939 }
940 return -1;
941}
942
943const lldb_private::ArchSpec &
944GDBRemoteCommunicationClient::GetHostArchitecture ()
945{
Greg Claytonb3448432011-03-24 21:19:54 +0000946 if (m_supports_qHostInfo == eLazyBoolCalculate)
Greg Clayton61d043b2011-03-22 04:00:09 +0000947 GetHostInfo ();
Greg Claytoncb8977d2011-03-23 00:09:55 +0000948 return m_host_arch;
Greg Clayton61d043b2011-03-22 04:00:09 +0000949}
950
951addr_t
952GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
953{
954 char packet[64];
955 ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
956 permissions & lldb::ePermissionsReadable ? "r" : "",
957 permissions & lldb::ePermissionsWritable ? "w" : "",
958 permissions & lldb::ePermissionsExecutable ? "x" : "");
959 StringExtractorGDBRemote response;
960 if (SendPacketAndWaitForResponse (packet, response, false))
961 {
962 if (!response.IsErrorResponse())
963 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
964 }
965 return LLDB_INVALID_ADDRESS;
966}
967
968bool
969GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
970{
971 char packet[64];
972 snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
973 StringExtractorGDBRemote response;
974 if (SendPacketAndWaitForResponse (packet, response, false))
975 {
976 if (response.IsOKResponse())
977 return true;
978 }
979 return false;
980}
981
982int
983GDBRemoteCommunicationClient::SetSTDIN (char const *path)
984{
985 if (path && path[0])
986 {
987 StreamString packet;
988 packet.PutCString("QSetSTDIN:");
989 packet.PutBytesAsRawHex8(path, strlen(path));
990
991 StringExtractorGDBRemote response;
992 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
993 {
994 if (response.IsOKResponse())
995 return 0;
996 uint8_t error = response.GetError();
997 if (error)
998 return error;
999 }
1000 }
1001 return -1;
1002}
1003
1004int
1005GDBRemoteCommunicationClient::SetSTDOUT (char const *path)
1006{
1007 if (path && path[0])
1008 {
1009 StreamString packet;
1010 packet.PutCString("QSetSTDOUT:");
1011 packet.PutBytesAsRawHex8(path, strlen(path));
1012
1013 StringExtractorGDBRemote response;
1014 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1015 {
1016 if (response.IsOKResponse())
1017 return 0;
1018 uint8_t error = response.GetError();
1019 if (error)
1020 return error;
1021 }
1022 }
1023 return -1;
1024}
1025
1026int
1027GDBRemoteCommunicationClient::SetSTDERR (char const *path)
1028{
1029 if (path && path[0])
1030 {
1031 StreamString packet;
1032 packet.PutCString("QSetSTDERR:");
1033 packet.PutBytesAsRawHex8(path, strlen(path));
1034
1035 StringExtractorGDBRemote response;
1036 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1037 {
1038 if (response.IsOKResponse())
1039 return 0;
1040 uint8_t error = response.GetError();
1041 if (error)
1042 return error;
1043 }
1044 }
1045 return -1;
1046}
1047
1048int
1049GDBRemoteCommunicationClient::SetWorkingDir (char const *path)
1050{
1051 if (path && path[0])
1052 {
1053 StreamString packet;
1054 packet.PutCString("QSetWorkingDir:");
1055 packet.PutBytesAsRawHex8(path, strlen(path));
1056
1057 StringExtractorGDBRemote response;
1058 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1059 {
1060 if (response.IsOKResponse())
1061 return 0;
1062 uint8_t error = response.GetError();
1063 if (error)
1064 return error;
1065 }
1066 }
1067 return -1;
1068}
1069
1070int
1071GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
1072{
1073 StreamString packet;
1074 packet.Printf("QSetDisableASLR:%i", enable ? 1 : 0);
1075
1076 StringExtractorGDBRemote response;
1077 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1078 {
1079 if (response.IsOKResponse())
1080 return 0;
1081 uint8_t error = response.GetError();
1082 if (error)
1083 return error;
1084 }
1085 return -1;
1086}