blob: d0198a0db095a4e4cc7d177552b9d31ec89bf845 [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),
Greg Clayton61d043b2011-03-22 04:00:09 +000041 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),
Greg Clayton24bc5d92011-03-30 18:16:51 +000047 m_qHostInfo_is_valid (eLazyBoolCalculate),
48 m_supports_qProcessInfoPID (true),
49 m_supports_qfProcessInfo (true),
50 m_supports_qUserName (true),
51 m_supports_qGroupName (true),
Greg Clayton61d043b2011-03-22 04:00:09 +000052 m_async_mutex (Mutex::eMutexTypeRecursive),
53 m_async_packet_predicate (false),
54 m_async_packet (),
55 m_async_response (),
56 m_async_signal (-1),
Greg Clayton58e26e02011-03-24 04:28:38 +000057 m_host_arch(),
58 m_os_version_major (UINT32_MAX),
59 m_os_version_minor (UINT32_MAX),
60 m_os_version_update (UINT32_MAX)
Greg Clayton61d043b2011-03-22 04:00:09 +000061{
62 m_rx_packet_listener.StartListeningForEvents(this,
63 Communication::eBroadcastBitPacketAvailable |
64 Communication::eBroadcastBitReadThreadDidExit);
65}
66
67//----------------------------------------------------------------------
68// Destructor
69//----------------------------------------------------------------------
70GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient()
71{
72 m_rx_packet_listener.StopListeningForEvents(this,
73 Communication::eBroadcastBitPacketAvailable |
74 Communication::eBroadcastBitReadThreadDidExit);
75 if (IsConnected())
76 {
77 StopReadThread();
78 Disconnect();
79 }
80}
81
82bool
Greg Clayton58e26e02011-03-24 04:28:38 +000083GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
84{
85 // Start the read thread after we send the handshake ack since if we
86 // fail to send the handshake ack, there is no reason to continue...
87 if (SendAck())
88 return StartReadThread (error_ptr);
89
90 if (error_ptr)
91 error_ptr->SetErrorString("failed to send the handshake ack");
92 return false;
93}
94
95void
96GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
Greg Clayton61d043b2011-03-22 04:00:09 +000097{
98 if (m_supports_not_sending_acks == eLazyBoolCalculate)
99 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000100 m_send_acks = true;
Greg Clayton61d043b2011-03-22 04:00:09 +0000101 m_supports_not_sending_acks = eLazyBoolNo;
Greg Clayton58e26e02011-03-24 04:28:38 +0000102
103 StringExtractorGDBRemote response;
Greg Clayton61d043b2011-03-22 04:00:09 +0000104 if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false))
105 {
106 if (response.IsOKResponse())
Greg Clayton58e26e02011-03-24 04:28:38 +0000107 {
108 m_send_acks = false;
Greg Clayton61d043b2011-03-22 04:00:09 +0000109 m_supports_not_sending_acks = eLazyBoolYes;
Greg Clayton58e26e02011-03-24 04:28:38 +0000110 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000111 }
112 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000113}
114
115void
116GDBRemoteCommunicationClient::ResetDiscoverableSettings()
117{
118 m_supports_not_sending_acks = eLazyBoolCalculate;
119 m_supports_thread_suffix = eLazyBoolCalculate;
Greg Clayton61d043b2011-03-22 04:00:09 +0000120 m_supports_vCont_c = eLazyBoolCalculate;
121 m_supports_vCont_C = eLazyBoolCalculate;
122 m_supports_vCont_s = eLazyBoolCalculate;
123 m_supports_vCont_S = eLazyBoolCalculate;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000124 m_qHostInfo_is_valid = eLazyBoolCalculate;
125 m_supports_qProcessInfoPID = true;
126 m_supports_qfProcessInfo = true;
127 m_supports_qUserName = true;
128 m_supports_qGroupName = true;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000129 m_host_arch.Clear();
Greg Clayton61d043b2011-03-22 04:00:09 +0000130}
131
132
133bool
134GDBRemoteCommunicationClient::GetThreadSuffixSupported ()
135{
136 if (m_supports_thread_suffix == eLazyBoolCalculate)
137 {
138 StringExtractorGDBRemote response;
139 m_supports_thread_suffix = eLazyBoolNo;
140 if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false))
141 {
142 if (response.IsOKResponse())
143 m_supports_thread_suffix = eLazyBoolYes;
144 }
145 }
146 return m_supports_thread_suffix;
147}
148bool
149GDBRemoteCommunicationClient::GetVContSupported (char flavor)
150{
151 if (m_supports_vCont_c == eLazyBoolCalculate)
152 {
153 StringExtractorGDBRemote response;
154 m_supports_vCont_any = eLazyBoolNo;
155 m_supports_vCont_all = eLazyBoolNo;
156 m_supports_vCont_c = eLazyBoolNo;
157 m_supports_vCont_C = eLazyBoolNo;
158 m_supports_vCont_s = eLazyBoolNo;
159 m_supports_vCont_S = eLazyBoolNo;
160 if (SendPacketAndWaitForResponse("vCont?", response, false))
161 {
162 const char *response_cstr = response.GetStringRef().c_str();
163 if (::strstr (response_cstr, ";c"))
164 m_supports_vCont_c = eLazyBoolYes;
165
166 if (::strstr (response_cstr, ";C"))
167 m_supports_vCont_C = eLazyBoolYes;
168
169 if (::strstr (response_cstr, ";s"))
170 m_supports_vCont_s = eLazyBoolYes;
171
172 if (::strstr (response_cstr, ";S"))
173 m_supports_vCont_S = eLazyBoolYes;
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_all = eLazyBoolYes;
181 }
182
183 if (m_supports_vCont_c == eLazyBoolYes ||
184 m_supports_vCont_C == eLazyBoolYes ||
185 m_supports_vCont_s == eLazyBoolYes ||
186 m_supports_vCont_S == eLazyBoolYes)
187 {
188 m_supports_vCont_any = eLazyBoolYes;
189 }
190 }
191 }
192
193 switch (flavor)
194 {
195 case 'a': return m_supports_vCont_any;
196 case 'A': return m_supports_vCont_all;
197 case 'c': return m_supports_vCont_c;
198 case 'C': return m_supports_vCont_C;
199 case 's': return m_supports_vCont_s;
200 case 'S': return m_supports_vCont_S;
201 default: break;
202 }
203 return false;
204}
205
206
207size_t
208GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
209(
210 const char *payload,
211 StringExtractorGDBRemote &response,
212 bool send_async
213)
214{
215 return SendPacketAndWaitForResponse (payload,
216 ::strlen (payload),
217 response,
218 send_async);
219}
220
221size_t
222GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
223(
224 const char *payload,
225 size_t payload_length,
226 StringExtractorGDBRemote &response,
227 bool send_async
228)
229{
230 Mutex::Locker locker;
231 TimeValue timeout_time;
232 timeout_time = TimeValue::Now();
233 timeout_time.OffsetWithSeconds (m_packet_timeout);
234 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
235
236 if (GetSequenceMutex (locker))
237 {
238 if (SendPacketNoLock (payload, strlen(payload)))
239 return WaitForPacketNoLock (response, &timeout_time);
240 }
241 else
242 {
243 if (send_async)
244 {
245 Mutex::Locker async_locker (m_async_mutex);
246 m_async_packet.assign(payload, payload_length);
247 m_async_packet_predicate.SetValue (true, eBroadcastNever);
248
249 if (log)
250 log->Printf ("async: async packet = %s", m_async_packet.c_str());
251
252 bool timed_out = false;
253 bool sent_interrupt = false;
254 if (SendInterrupt(locker, 2, sent_interrupt, timed_out))
255 {
256 if (sent_interrupt)
257 {
258 if (log)
259 log->Printf ("async: sent interrupt");
260 if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
261 {
262 if (log)
263 log->Printf ("async: got response");
264 response = m_async_response;
265 return response.GetStringRef().size();
266 }
267 else
268 {
269 if (log)
270 log->Printf ("async: timed out waiting for response");
271 }
272
273 // Make sure we wait until the continue packet has been sent again...
274 if (m_private_is_running.WaitForValueEqualTo (true, &timeout_time, &timed_out))
275 {
276 if (log)
277 log->Printf ("async: timed out waiting for process to resume");
278 }
279 }
280 else
281 {
282 // We had a racy condition where we went to send the interrupt
283 // yet we were able to get the loc
284 }
285 }
286 else
287 {
288 if (log)
289 log->Printf ("async: failed to interrupt");
290 }
291 }
292 else
293 {
294 if (log)
295 log->Printf ("mutex taken and send_async == false, aborting packet");
296 }
297 }
298 return 0;
299}
300
301//template<typename _Tp>
302//class ScopedValueChanger
303//{
304//public:
305// // Take a value reference and the value to assign it to when this class
306// // instance goes out of scope.
307// ScopedValueChanger (_Tp &value_ref, _Tp value) :
308// m_value_ref (value_ref),
309// m_value (value)
310// {
311// }
312//
313// // This object is going out of scope, change the value pointed to by
314// // m_value_ref to the value we got during construction which was stored in
315// // m_value;
316// ~ScopedValueChanger ()
317// {
318// m_value_ref = m_value;
319// }
320//protected:
321// _Tp &m_value_ref; // A reference to the value we will change when this object destructs
322// _Tp m_value; // The value to assign to m_value_ref when this goes out of scope.
323//};
324
325StateType
326GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
327(
328 ProcessGDBRemote *process,
329 const char *payload,
330 size_t packet_length,
331 StringExtractorGDBRemote &response
332)
333{
334 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
335 if (log)
336 log->Printf ("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
337
338 Mutex::Locker locker(m_sequence_mutex);
339 StateType state = eStateRunning;
340
341 BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
342 m_public_is_running.SetValue (true, eBroadcastNever);
343 // Set the starting continue packet into "continue_packet". This packet
344 // make change if we are interrupted and we continue after an async packet...
345 std::string continue_packet(payload, packet_length);
346
347 while (state == eStateRunning)
348 {
349 if (log)
350 log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
351 if (SendPacket(continue_packet.c_str(), continue_packet.size()) == 0)
352 state = eStateInvalid;
353
354 m_private_is_running.SetValue (true, eBroadcastNever);
355
356 if (log)
357 log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%.*s)", __FUNCTION__);
358
359 if (WaitForPacket (response, (TimeValue*)NULL))
360 {
361 if (response.Empty())
362 state = eStateInvalid;
363 else
364 {
365 const char stop_type = response.GetChar();
366 if (log)
367 log->Printf ("GDBRemoteCommunicationClient::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str());
368 switch (stop_type)
369 {
370 case 'T':
371 case 'S':
372 if (process->GetStopID() == 0)
373 {
374 if (process->GetID() == LLDB_INVALID_PROCESS_ID)
375 {
376 lldb::pid_t pid = GetCurrentProcessID ();
377 if (pid != LLDB_INVALID_PROCESS_ID)
378 process->SetID (pid);
379 }
380 process->BuildDynamicRegisterInfo (true);
381 }
382
383 // Privately notify any internal threads that we have stopped
384 // in case we wanted to interrupt our process, yet we might
385 // send a packet and continue without returning control to the
386 // user.
387 m_private_is_running.SetValue (false, eBroadcastAlways);
388 if (m_async_signal != -1)
389 {
390 if (log)
391 log->Printf ("async: send signo = %s", Host::GetSignalAsCString (m_async_signal));
392
393 // Save off the async signal we are supposed to send
394 const int async_signal = m_async_signal;
395 // Clear the async signal member so we don't end up
396 // sending the signal multiple times...
397 m_async_signal = -1;
398 // Check which signal we stopped with
399 uint8_t signo = response.GetHexU8(255);
400 if (signo == async_signal)
401 {
402 if (log)
403 log->Printf ("async: stopped with signal %s, we are done running", Host::GetSignalAsCString (signo));
404
405 // We already stopped with a signal that we wanted
406 // to stop with, so we are done
407 response.SetFilePos (0);
408 }
409 else
410 {
411 // We stopped with a different signal that the one
412 // we wanted to stop with, so now we must resume
413 // with the signal we want
414 char signal_packet[32];
415 int signal_packet_len = 0;
416 signal_packet_len = ::snprintf (signal_packet,
417 sizeof (signal_packet),
418 "C%2.2x",
419 async_signal);
420
421 if (log)
422 log->Printf ("async: stopped with signal %s, resume with %s",
423 Host::GetSignalAsCString (signo),
424 Host::GetSignalAsCString (async_signal));
425
426 // Set the continue packet to resume...
427 continue_packet.assign(signal_packet, signal_packet_len);
428 continue;
429 }
430 }
431 else if (m_async_packet_predicate.GetValue())
432 {
433 // We are supposed to send an asynchronous packet while
434 // we are running.
435 m_async_response.Clear();
436 if (m_async_packet.empty())
437 {
438 if (log)
439 log->Printf ("async: error: empty async packet");
440
441 }
442 else
443 {
444 if (log)
445 log->Printf ("async: sending packet: %s",
446 m_async_packet.c_str());
447
448 SendPacketAndWaitForResponse (&m_async_packet[0],
449 m_async_packet.size(),
450 m_async_response,
451 false);
452 }
453 // Let the other thread that was trying to send the async
454 // packet know that the packet has been sent and response is
455 // ready...
456 m_async_packet_predicate.SetValue(false, eBroadcastAlways);
457
458 // Set the continue packet to resume...
459 continue_packet.assign (1, 'c');
460 continue;
461 }
462 // Stop with signal and thread info
463 state = eStateStopped;
464 break;
465
466 case 'W':
467 case 'X':
468 // process exited
469 state = eStateExited;
470 break;
471
472 case 'O':
473 // STDOUT
474 {
475 std::string inferior_stdout;
476 inferior_stdout.reserve(response.GetBytesLeft () / 2);
477 char ch;
478 while ((ch = response.GetHexU8()) != '\0')
479 inferior_stdout.append(1, ch);
480 process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
481 }
482 break;
483
484 case 'E':
485 // ERROR
486 state = eStateInvalid;
487 break;
488
489 default:
490 if (log)
491 log->Printf ("GDBRemoteCommunicationClient::%s () unrecognized async packet", __FUNCTION__);
492 state = eStateInvalid;
493 break;
494 }
495 }
496 }
497 else
498 {
499 if (log)
500 log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(...) => false", __FUNCTION__);
501 state = eStateInvalid;
502 }
503 }
504 if (log)
505 log->Printf ("GDBRemoteCommunicationClient::%s () => %s", __FUNCTION__, StateAsCString(state));
506 response.SetFilePos(0);
507 m_private_is_running.SetValue (false, eBroadcastAlways);
508 m_public_is_running.SetValue (false, eBroadcastAlways);
509 return state;
510}
511
512bool
513GDBRemoteCommunicationClient::SendAsyncSignal (int signo)
514{
515 m_async_signal = signo;
516 bool timed_out = false;
517 bool sent_interrupt = false;
518 Mutex::Locker locker;
519 if (SendInterrupt (locker, 1, sent_interrupt, timed_out))
520 return true;
521 m_async_signal = -1;
522 return false;
523}
524
525// This function takes a mutex locker as a parameter in case the GetSequenceMutex
526// actually succeeds. If it doesn't succeed in acquiring the sequence mutex
527// (the expected result), then it will send the halt packet. If it does succeed
528// then the caller that requested the interrupt will want to keep the sequence
529// locked down so that no one else can send packets while the caller has control.
530// This function usually gets called when we are running and need to stop the
531// target. It can also be used when we are running and and we need to do something
532// else (like read/write memory), so we need to interrupt the running process
533// (gdb remote protocol requires this), and do what we need to do, then resume.
534
535bool
536GDBRemoteCommunicationClient::SendInterrupt
537(
538 Mutex::Locker& locker,
539 uint32_t seconds_to_wait_for_stop,
540 bool &sent_interrupt,
541 bool &timed_out
542)
543{
544 sent_interrupt = false;
545 timed_out = false;
546 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
547
548 if (IsRunning())
549 {
550 // Only send an interrupt if our debugserver is running...
551 if (GetSequenceMutex (locker) == false)
552 {
553 // Someone has the mutex locked waiting for a response or for the
554 // inferior to stop, so send the interrupt on the down low...
555 char ctrl_c = '\x03';
556 ConnectionStatus status = eConnectionStatusSuccess;
557 TimeValue timeout;
558 if (seconds_to_wait_for_stop)
559 {
560 timeout = TimeValue::Now();
561 timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
562 }
563 size_t bytes_written = Write (&ctrl_c, 1, status, NULL);
564 ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_PROCESS, "send packet: \\x03");
565 if (bytes_written > 0)
566 {
567 sent_interrupt = true;
568 if (seconds_to_wait_for_stop)
569 {
570 if (m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out))
571 {
572 if (log)
573 log->Printf ("GDBRemoteCommunicationClient::%s () - sent interrupt, private state stopped", __FUNCTION__);
574 return true;
575 }
576 else
577 {
578 if (log)
579 log->Printf ("GDBRemoteCommunicationClient::%s () - sent interrupt, timed out wating for async thread resume", __FUNCTION__);
580 }
581 }
582 else
583 {
584 if (log)
585 log->Printf ("GDBRemoteCommunicationClient::%s () - sent interrupt, not waiting for stop...", __FUNCTION__);
586 return true;
587 }
588 }
589 else
590 {
591 if (log)
592 log->Printf ("GDBRemoteCommunicationClient::%s () - failed to write interrupt", __FUNCTION__);
593 }
594 return false;
595 }
596 else
597 {
598 if (log)
599 log->Printf ("GDBRemoteCommunicationClient::%s () - got sequence mutex without having to interrupt", __FUNCTION__);
600 }
601 }
602 return true;
603}
604
605lldb::pid_t
606GDBRemoteCommunicationClient::GetCurrentProcessID ()
607{
608 StringExtractorGDBRemote response;
609 if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false))
610 {
611 if (response.GetChar() == 'Q')
612 if (response.GetChar() == 'C')
613 return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
614 }
615 return LLDB_INVALID_PROCESS_ID;
616}
617
618bool
619GDBRemoteCommunicationClient::GetLaunchSuccess (std::string &error_str)
620{
621 error_str.clear();
622 StringExtractorGDBRemote response;
623 if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, false))
624 {
625 if (response.IsOKResponse())
626 return true;
627 if (response.GetChar() == 'E')
628 {
629 // A string the describes what failed when launching...
630 error_str = response.GetStringRef().substr(1);
631 }
632 else
633 {
634 error_str.assign ("unknown error occurred launching process");
635 }
636 }
637 else
638 {
639 error_str.assign ("failed to send the qLaunchSuccess packet");
640 }
641 return false;
642}
643
644int
645GDBRemoteCommunicationClient::SendArgumentsPacket (char const *argv[])
646{
647 if (argv && argv[0])
648 {
649 StreamString packet;
650 packet.PutChar('A');
651 const char *arg;
652 for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
653 {
654 const int arg_len = strlen(arg);
655 if (i > 0)
656 packet.PutChar(',');
657 packet.Printf("%i,%i,", arg_len * 2, i);
658 packet.PutBytesAsRawHex8 (arg, arg_len);
659 }
660
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
674int
675GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_value)
676{
677 if (name_equal_value && name_equal_value[0])
678 {
679 StreamString packet;
680 packet.Printf("QEnvironment:%s", name_equal_value);
681 StringExtractorGDBRemote response;
682 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
683 {
684 if (response.IsOKResponse())
685 return 0;
686 uint8_t error = response.GetError();
687 if (error)
688 return error;
689 }
690 }
691 return -1;
692}
693
694bool
Greg Clayton58e26e02011-03-24 04:28:38 +0000695GDBRemoteCommunicationClient::GetOSVersion (uint32_t &major,
696 uint32_t &minor,
697 uint32_t &update)
698{
699 if (GetHostInfo ())
700 {
701 if (m_os_version_major != UINT32_MAX)
702 {
703 major = m_os_version_major;
704 minor = m_os_version_minor;
705 update = m_os_version_update;
706 return true;
707 }
708 }
709 return false;
710}
711
712bool
713GDBRemoteCommunicationClient::GetOSBuildString (std::string &s)
714{
715 if (GetHostInfo ())
716 {
717 if (!m_os_build.empty())
718 {
719 s = m_os_build;
720 return true;
721 }
722 }
723 s.clear();
724 return false;
725}
726
727
728bool
729GDBRemoteCommunicationClient::GetOSKernelDescription (std::string &s)
730{
731 if (GetHostInfo ())
732 {
733 if (!m_os_kernel.empty())
734 {
735 s = m_os_kernel;
736 return true;
737 }
738 }
739 s.clear();
740 return false;
741}
742
743bool
744GDBRemoteCommunicationClient::GetHostname (std::string &s)
745{
746 if (GetHostInfo ())
747 {
748 if (!m_hostname.empty())
749 {
750 s = m_hostname;
751 return true;
752 }
753 }
754 s.clear();
755 return false;
756}
757
758ArchSpec
759GDBRemoteCommunicationClient::GetSystemArchitecture ()
760{
761 if (GetHostInfo ())
762 return m_host_arch;
763 return ArchSpec();
764}
765
766
767bool
Greg Clayton06d7cc82011-04-04 18:18:57 +0000768GDBRemoteCommunicationClient::GetHostInfo (bool force)
Greg Clayton61d043b2011-03-22 04:00:09 +0000769{
Greg Clayton06d7cc82011-04-04 18:18:57 +0000770 if (force || m_qHostInfo_is_valid == eLazyBoolCalculate)
Greg Clayton61d043b2011-03-22 04:00:09 +0000771 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000772 m_qHostInfo_is_valid = eLazyBoolNo;
Greg Clayton61d043b2011-03-22 04:00:09 +0000773 StringExtractorGDBRemote response;
774 if (SendPacketAndWaitForResponse ("qHostInfo", response, false))
775 {
776 if (response.IsUnsupportedResponse())
Greg Clayton24bc5d92011-03-30 18:16:51 +0000777 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000778 return false;
Greg Clayton61d043b2011-03-22 04:00:09 +0000779 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000780 else if (response.IsNormalResponse())
Greg Claytoncb8977d2011-03-23 00:09:55 +0000781 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000782 std::string name;
783 std::string value;
784 uint32_t cpu = LLDB_INVALID_CPUTYPE;
785 uint32_t sub = 0;
786 std::string arch_name;
787 std::string os_name;
788 std::string vendor_name;
789 std::string triple;
790 uint32_t pointer_byte_size = 0;
791 StringExtractor extractor;
792 ByteOrder byte_order = eByteOrderInvalid;
793 uint32_t num_keys_decoded = 0;
794 while (response.GetNameColonValue(name, value))
Greg Claytoncb8977d2011-03-23 00:09:55 +0000795 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000796 if (name.compare("cputype") == 0)
Greg Clayton58e26e02011-03-24 04:28:38 +0000797 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000798 // exception type in big endian hex
799 cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
800 if (cpu != LLDB_INVALID_CPUTYPE)
801 ++num_keys_decoded;
802 }
803 else if (name.compare("cpusubtype") == 0)
804 {
805 // exception count in big endian hex
806 sub = Args::StringToUInt32 (value.c_str(), 0, 0);
807 if (sub != 0)
808 ++num_keys_decoded;
809 }
810 else if (name.compare("arch") == 0)
811 {
812 arch_name.swap (value);
813 ++num_keys_decoded;
814 }
815 else if (name.compare("triple") == 0)
816 {
817 // The triple comes as ASCII hex bytes since it contains '-' chars
818 extractor.GetStringRef().swap(value);
819 extractor.SetFilePos(0);
820 extractor.GetHexByteString (triple);
821 ++num_keys_decoded;
822 }
823 else if (name.compare("os_build") == 0)
824 {
825 extractor.GetStringRef().swap(value);
826 extractor.SetFilePos(0);
827 extractor.GetHexByteString (m_os_build);
828 ++num_keys_decoded;
829 }
830 else if (name.compare("hostname") == 0)
831 {
832 extractor.GetStringRef().swap(value);
833 extractor.SetFilePos(0);
834 extractor.GetHexByteString (m_hostname);
835 ++num_keys_decoded;
836 }
837 else if (name.compare("os_kernel") == 0)
838 {
839 extractor.GetStringRef().swap(value);
840 extractor.SetFilePos(0);
841 extractor.GetHexByteString (m_os_kernel);
842 ++num_keys_decoded;
843 }
844 else if (name.compare("ostype") == 0)
845 {
846 os_name.swap (value);
847 ++num_keys_decoded;
848 }
849 else if (name.compare("vendor") == 0)
850 {
851 vendor_name.swap(value);
852 ++num_keys_decoded;
853 }
854 else if (name.compare("endian") == 0)
855 {
856 ++num_keys_decoded;
857 if (value.compare("little") == 0)
858 byte_order = eByteOrderLittle;
859 else if (value.compare("big") == 0)
860 byte_order = eByteOrderBig;
861 else if (value.compare("pdp") == 0)
862 byte_order = eByteOrderPDP;
863 else
864 --num_keys_decoded;
865 }
866 else if (name.compare("ptrsize") == 0)
867 {
868 pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
869 if (pointer_byte_size != 0)
870 ++num_keys_decoded;
871 }
872 else if (name.compare("os_version") == 0)
873 {
874 Args::StringToVersion (value.c_str(),
875 m_os_version_major,
876 m_os_version_minor,
877 m_os_version_update);
878 if (m_os_version_major != UINT32_MAX)
879 ++num_keys_decoded;
880 }
881 }
882
883 if (num_keys_decoded > 0)
884 m_qHostInfo_is_valid = eLazyBoolYes;
885
886 if (triple.empty())
887 {
888 if (arch_name.empty())
889 {
890 if (cpu != LLDB_INVALID_CPUTYPE)
891 {
892 m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
893 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 }
901 if (!vendor_name.empty())
902 m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
903 if (!os_name.empty())
904 m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name));
905
906 }
907 }
908 else
909 {
910 std::string triple;
911 triple += arch_name;
912 triple += '-';
913 if (vendor_name.empty())
914 triple += "unknown";
915 else
916 triple += vendor_name;
917 triple += '-';
918 if (os_name.empty())
919 triple += "unknown";
920 else
921 triple += os_name;
922 m_host_arch.SetTriple (triple.c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000923 if (pointer_byte_size)
924 {
925 assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
926 }
927 if (byte_order != eByteOrderInvalid)
928 {
929 assert (byte_order == m_host_arch.GetByteOrder());
930 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000931
Greg Clayton58e26e02011-03-24 04:28:38 +0000932 }
933 }
934 else
935 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000936 m_host_arch.SetTriple (triple.c_str());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000937 if (pointer_byte_size)
938 {
939 assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
940 }
941 if (byte_order != eByteOrderInvalid)
942 {
943 assert (byte_order == m_host_arch.GetByteOrder());
944 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000945 }
Greg Claytoncb8977d2011-03-23 00:09:55 +0000946 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000947 }
948 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000949 return m_qHostInfo_is_valid == eLazyBoolYes;
Greg Clayton61d043b2011-03-22 04:00:09 +0000950}
951
952int
953GDBRemoteCommunicationClient::SendAttach
954(
955 lldb::pid_t pid,
956 StringExtractorGDBRemote& response
957)
958{
959 if (pid != LLDB_INVALID_PROCESS_ID)
960 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000961 char packet[64];
962 const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%x", pid);
963 assert (packet_len < sizeof(packet));
964 if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
Greg Clayton61d043b2011-03-22 04:00:09 +0000965 {
966 if (response.IsErrorResponse())
967 return response.GetError();
968 return 0;
969 }
970 }
971 return -1;
972}
973
974const lldb_private::ArchSpec &
975GDBRemoteCommunicationClient::GetHostArchitecture ()
976{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000977 if (m_qHostInfo_is_valid == eLazyBoolCalculate)
Greg Clayton61d043b2011-03-22 04:00:09 +0000978 GetHostInfo ();
Greg Claytoncb8977d2011-03-23 00:09:55 +0000979 return m_host_arch;
Greg Clayton61d043b2011-03-22 04:00:09 +0000980}
981
982addr_t
983GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
984{
985 char packet[64];
Greg Clayton24bc5d92011-03-30 18:16:51 +0000986 const int packet_len = ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
987 permissions & lldb::ePermissionsReadable ? "r" : "",
988 permissions & lldb::ePermissionsWritable ? "w" : "",
989 permissions & lldb::ePermissionsExecutable ? "x" : "");
990 assert (packet_len < sizeof(packet));
Greg Clayton61d043b2011-03-22 04:00:09 +0000991 StringExtractorGDBRemote response;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000992 if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
Greg Clayton61d043b2011-03-22 04:00:09 +0000993 {
994 if (!response.IsErrorResponse())
995 return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
996 }
997 return LLDB_INVALID_ADDRESS;
998}
999
1000bool
1001GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
1002{
1003 char packet[64];
Greg Clayton24bc5d92011-03-30 18:16:51 +00001004 const int packet_len = ::snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
1005 assert (packet_len < sizeof(packet));
Greg Clayton61d043b2011-03-22 04:00:09 +00001006 StringExtractorGDBRemote response;
Greg Clayton24bc5d92011-03-30 18:16:51 +00001007 if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
Greg Clayton61d043b2011-03-22 04:00:09 +00001008 {
1009 if (response.IsOKResponse())
1010 return true;
1011 }
1012 return false;
1013}
1014
1015int
1016GDBRemoteCommunicationClient::SetSTDIN (char const *path)
1017{
1018 if (path && path[0])
1019 {
1020 StreamString packet;
1021 packet.PutCString("QSetSTDIN:");
1022 packet.PutBytesAsRawHex8(path, strlen(path));
1023
1024 StringExtractorGDBRemote response;
1025 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1026 {
1027 if (response.IsOKResponse())
1028 return 0;
1029 uint8_t error = response.GetError();
1030 if (error)
1031 return error;
1032 }
1033 }
1034 return -1;
1035}
1036
1037int
1038GDBRemoteCommunicationClient::SetSTDOUT (char const *path)
1039{
1040 if (path && path[0])
1041 {
1042 StreamString packet;
1043 packet.PutCString("QSetSTDOUT:");
1044 packet.PutBytesAsRawHex8(path, strlen(path));
1045
1046 StringExtractorGDBRemote response;
1047 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1048 {
1049 if (response.IsOKResponse())
1050 return 0;
1051 uint8_t error = response.GetError();
1052 if (error)
1053 return error;
1054 }
1055 }
1056 return -1;
1057}
1058
1059int
1060GDBRemoteCommunicationClient::SetSTDERR (char const *path)
1061{
1062 if (path && path[0])
1063 {
1064 StreamString packet;
1065 packet.PutCString("QSetSTDERR:");
1066 packet.PutBytesAsRawHex8(path, strlen(path));
1067
1068 StringExtractorGDBRemote response;
1069 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1070 {
1071 if (response.IsOKResponse())
1072 return 0;
1073 uint8_t error = response.GetError();
1074 if (error)
1075 return error;
1076 }
1077 }
1078 return -1;
1079}
1080
1081int
1082GDBRemoteCommunicationClient::SetWorkingDir (char const *path)
1083{
1084 if (path && path[0])
1085 {
1086 StreamString packet;
1087 packet.PutCString("QSetWorkingDir:");
1088 packet.PutBytesAsRawHex8(path, strlen(path));
1089
1090 StringExtractorGDBRemote response;
1091 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1092 {
1093 if (response.IsOKResponse())
1094 return 0;
1095 uint8_t error = response.GetError();
1096 if (error)
1097 return error;
1098 }
1099 }
1100 return -1;
1101}
1102
1103int
1104GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
1105{
Greg Clayton24bc5d92011-03-30 18:16:51 +00001106 char packet[32];
1107 const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDisableASLR:%i", enable ? 1 : 0);
1108 assert (packet_len < sizeof(packet));
Greg Clayton61d043b2011-03-22 04:00:09 +00001109 StringExtractorGDBRemote response;
Greg Clayton24bc5d92011-03-30 18:16:51 +00001110 if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
Greg Clayton61d043b2011-03-22 04:00:09 +00001111 {
1112 if (response.IsOKResponse())
1113 return 0;
1114 uint8_t error = response.GetError();
1115 if (error)
1116 return error;
1117 }
1118 return -1;
1119}
Greg Clayton24bc5d92011-03-30 18:16:51 +00001120
1121bool
1122GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInfo &process_info)
1123{
1124 if (response.IsNormalResponse())
1125 {
1126 std::string name;
1127 std::string value;
1128 StringExtractor extractor;
1129
1130 while (response.GetNameColonValue(name, value))
1131 {
1132 if (name.compare("pid") == 0)
1133 {
1134 process_info.SetProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0));
1135 }
1136 else if (name.compare("ppid") == 0)
1137 {
1138 process_info.SetParentProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0));
1139 }
1140 else if (name.compare("uid") == 0)
1141 {
1142 process_info.SetRealUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
1143 }
1144 else if (name.compare("euid") == 0)
1145 {
1146 process_info.SetEffectiveUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
1147 }
1148 else if (name.compare("gid") == 0)
1149 {
1150 process_info.SetRealGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
1151 }
1152 else if (name.compare("egid") == 0)
1153 {
1154 process_info.SetEffectiveGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
1155 }
1156 else if (name.compare("triple") == 0)
1157 {
1158 // The triple comes as ASCII hex bytes since it contains '-' chars
1159 extractor.GetStringRef().swap(value);
1160 extractor.SetFilePos(0);
1161 extractor.GetHexByteString (value);
1162 process_info.GetArchitecture ().SetTriple (value.c_str());
1163 }
1164 else if (name.compare("name") == 0)
1165 {
1166 StringExtractor extractor;
1167 // The the process name from ASCII hex bytes since we can't
1168 // control the characters in a process name
1169 extractor.GetStringRef().swap(value);
1170 extractor.SetFilePos(0);
1171 extractor.GetHexByteString (value);
Greg Claytonff39f742011-04-01 00:29:43 +00001172 process_info.SetName (value.c_str());
Greg Clayton24bc5d92011-03-30 18:16:51 +00001173 }
1174 }
1175
1176 if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
1177 return true;
1178 }
1179 return false;
1180}
1181
1182bool
1183GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
1184{
1185 process_info.Clear();
1186
1187 if (m_supports_qProcessInfoPID)
1188 {
1189 char packet[32];
1190 const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%i", pid);
1191 assert (packet_len < sizeof(packet));
1192 StringExtractorGDBRemote response;
1193 if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
1194 {
1195 if (response.IsUnsupportedResponse())
1196 {
1197 m_supports_qProcessInfoPID = false;
1198 return false;
1199 }
1200
1201 return DecodeProcessInfoResponse (response, process_info);
1202 }
1203 }
1204 return false;
1205}
1206
1207uint32_t
1208GDBRemoteCommunicationClient::FindProcesses (const ProcessInfoMatch &match_info,
1209 ProcessInfoList &process_infos)
1210{
1211 process_infos.Clear();
1212
1213 if (m_supports_qfProcessInfo)
1214 {
1215 StreamString packet;
1216 packet.PutCString ("qfProcessInfo");
1217 if (!match_info.MatchAllProcesses())
1218 {
1219 packet.PutChar (':');
1220 const char *name = match_info.GetProcessInfo().GetName();
1221 bool has_name_match = false;
1222 if (name && name[0])
1223 {
1224 has_name_match = true;
1225 NameMatchType name_match_type = match_info.GetNameMatchType();
1226 switch (name_match_type)
1227 {
1228 case eNameMatchIgnore:
1229 has_name_match = false;
1230 break;
1231
1232 case eNameMatchEquals:
1233 packet.PutCString ("name_match:equals;");
1234 break;
1235
1236 case eNameMatchContains:
1237 packet.PutCString ("name_match:contains;");
1238 break;
1239
1240 case eNameMatchStartsWith:
1241 packet.PutCString ("name_match:starts_with;");
1242 break;
1243
1244 case eNameMatchEndsWith:
1245 packet.PutCString ("name_match:ends_with;");
1246 break;
1247
1248 case eNameMatchRegularExpression:
1249 packet.PutCString ("name_match:regex;");
1250 break;
1251 }
1252 if (has_name_match)
1253 {
1254 packet.PutCString ("name:");
1255 packet.PutBytesAsRawHex8(name, ::strlen(name));
1256 packet.PutChar (';');
1257 }
1258 }
1259
1260 if (match_info.GetProcessInfo().ProcessIDIsValid())
1261 packet.Printf("pid:%u;",match_info.GetProcessInfo().GetProcessID());
1262 if (match_info.GetProcessInfo().ParentProcessIDIsValid())
1263 packet.Printf("parent_pid:%u;",match_info.GetProcessInfo().GetParentProcessID());
1264 if (match_info.GetProcessInfo().RealUserIDIsValid())
1265 packet.Printf("uid:%u;",match_info.GetProcessInfo().GetRealUserID());
1266 if (match_info.GetProcessInfo().RealGroupIDIsValid())
1267 packet.Printf("gid:%u;",match_info.GetProcessInfo().GetRealGroupID());
1268 if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
1269 packet.Printf("euid:%u;",match_info.GetProcessInfo().GetEffectiveUserID());
1270 if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
1271 packet.Printf("egid:%u;",match_info.GetProcessInfo().GetEffectiveGroupID());
1272 if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
1273 packet.Printf("all_users:%u;",match_info.GetMatchAllUsers() ? 1 : 0);
1274 if (match_info.GetProcessInfo().GetArchitecture().IsValid())
1275 {
1276 const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture();
1277 const llvm::Triple &triple = match_arch.GetTriple();
1278 packet.PutCString("triple:");
1279 packet.PutCStringAsRawHex8(triple.getTriple().c_str());
1280 packet.PutChar (';');
1281 }
1282 }
1283 StringExtractorGDBRemote response;
1284 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1285 {
1286 if (response.IsUnsupportedResponse())
1287 {
1288 m_supports_qfProcessInfo = false;
1289 return 0;
1290 }
1291
1292 do
1293 {
1294 ProcessInfo process_info;
1295 if (!DecodeProcessInfoResponse (response, process_info))
1296 break;
1297 process_infos.Append(process_info);
1298 response.GetStringRef().clear();
1299 response.SetFilePos(0);
1300 } while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false));
1301 }
1302 }
1303 return process_infos.GetSize();
1304
1305}
1306
1307bool
1308GDBRemoteCommunicationClient::GetUserName (uint32_t uid, std::string &name)
1309{
1310 if (m_supports_qUserName)
1311 {
1312 char packet[32];
1313 const int packet_len = ::snprintf (packet, sizeof (packet), "qUserName:%i", uid);
1314 assert (packet_len < sizeof(packet));
1315 StringExtractorGDBRemote response;
1316 if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
1317 {
1318 if (response.IsUnsupportedResponse())
1319 {
1320 m_supports_qUserName = false;
1321 return false;
1322 }
1323
1324 if (response.IsNormalResponse())
1325 {
1326 // Make sure we parsed the right number of characters. The response is
1327 // the hex encoded user name and should make up the entire packet.
1328 // If there are any non-hex ASCII bytes, the length won't match below..
1329 if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
1330 return true;
1331 }
1332 }
1333 }
1334 return false;
1335
1336}
1337
1338bool
1339GDBRemoteCommunicationClient::GetGroupName (uint32_t gid, std::string &name)
1340{
1341 if (m_supports_qGroupName)
1342 {
1343 char packet[32];
1344 const int packet_len = ::snprintf (packet, sizeof (packet), "qGroupName:%i", gid);
1345 assert (packet_len < sizeof(packet));
1346 StringExtractorGDBRemote response;
1347 if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
1348 {
1349 if (response.IsUnsupportedResponse())
1350 {
1351 m_supports_qGroupName = false;
1352 return false;
1353 }
1354
1355 if (response.IsNormalResponse())
1356 {
1357 // Make sure we parsed the right number of characters. The response is
1358 // the hex encoded group name and should make up the entire packet.
1359 // If there are any non-hex ASCII bytes, the length won't match below..
1360 if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
1361 return true;
1362 }
1363 }
1364 }
1365 return false;
Greg Clayton06d7cc82011-04-04 18:18:57 +00001366}
Greg Clayton24bc5d92011-03-30 18:16:51 +00001367
Greg Clayton06d7cc82011-04-04 18:18:57 +00001368void
1369GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets)
1370{
1371 uint32_t i;
1372 TimeValue start_time, end_time;
1373 uint64_t total_time_nsec;
1374 float packets_per_second;
1375 if (SendSpeedTestPacket (0, 0))
1376 {
1377 for (uint32_t send_size = 0; send_size <= 1024; send_size *= 2)
1378 {
1379 for (uint32_t recv_size = 0; recv_size <= 1024; recv_size *= 2)
1380 {
1381 start_time = TimeValue::Now();
1382 for (i=0; i<num_packets; ++i)
1383 {
1384 SendSpeedTestPacket (send_size, recv_size);
1385 }
1386 end_time = TimeValue::Now();
1387 total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
1388 packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)NSEC_PER_SEC;
1389 printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %llu.%09.9llu sec for %f packets/sec.\n",
1390 num_packets,
1391 send_size,
1392 recv_size,
1393 total_time_nsec / NSEC_PER_SEC,
1394 total_time_nsec % NSEC_PER_SEC,
1395 packets_per_second);
1396 if (recv_size == 0)
1397 recv_size = 32;
1398 }
1399 if (send_size == 0)
1400 send_size = 32;
1401 }
1402 }
1403 else
1404 {
1405 start_time = TimeValue::Now();
1406 for (i=0; i<num_packets; ++i)
1407 {
1408 GetCurrentProcessID ();
1409 }
1410 end_time = TimeValue::Now();
1411 total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
1412 packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)NSEC_PER_SEC;
1413 printf ("%u 'qC' packets packets in 0x%llu%09.9llu sec for %f packets/sec.\n",
1414 num_packets,
1415 total_time_nsec / NSEC_PER_SEC,
1416 total_time_nsec % NSEC_PER_SEC,
1417 packets_per_second);
1418 }
1419}
1420
1421bool
1422GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t recv_size)
1423{
1424 StreamString packet;
1425 packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size);
1426 uint32_t bytes_left = send_size;
1427 while (bytes_left > 0)
1428 {
1429 if (bytes_left >= 26)
1430 {
1431 packet.PutCString("abcdefghijklmnopqrstuvwxyz");
1432 bytes_left -= 26;
1433 }
1434 else
1435 {
1436 packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz");
1437 bytes_left = 0;
1438 }
1439 }
1440
1441 StringExtractorGDBRemote response;
1442 if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
1443 {
1444 if (response.IsUnsupportedResponse())
1445 return false;
1446 return true;
1447 }
1448 return false;
Greg Clayton24bc5d92011-03-30 18:16:51 +00001449}