1 //===-- CommunicationKDP.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 "CommunicationKDP.h"
12 
13 // C Includes
14 #include <errno.h>
15 #include <limits.h>
16 #include <string.h>
17 
18 // C++ Includes
19 #include "llvm/Support/MachO.h"
20 
21 // Other libraries and framework includes
22 #include "lldb/Core/DataBufferHeap.h"
23 #include "lldb/Core/DataExtractor.h"
24 #include "lldb/Core/Log.h"
25 #include "lldb/Core/State.h"
26 #include "lldb/Core/UUID.h"
27 #include "lldb/Host/FileSpec.h"
28 #include "lldb/Host/Host.h"
29 #include "lldb/Host/TimeValue.h"
30 #include "lldb/Target/Process.h"
31 
32 // Project includes
33 #include "ProcessKDPLog.h"
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 
38 //----------------------------------------------------------------------
39 // CommunicationKDP constructor
40 //----------------------------------------------------------------------
41 CommunicationKDP::CommunicationKDP (const char *comm_name) :
42     Communication(comm_name),
43     m_addr_byte_size (4),
44     m_byte_order (eByteOrderLittle),
45     m_packet_timeout (1),
46     m_sequence_mutex (Mutex::eMutexTypeRecursive),
47     m_is_running (false),
48     m_session_key (0u),
49     m_request_sequence_id (0u),
50     m_exception_sequence_id (0u),
51     m_kdp_version_version (0u),
52     m_kdp_version_feature (0u),
53     m_kdp_hostinfo_cpu_mask (0u),
54     m_kdp_hostinfo_cpu_type (0u),
55     m_kdp_hostinfo_cpu_subtype (0u)
56 {
57 }
58 
59 //----------------------------------------------------------------------
60 // Destructor
61 //----------------------------------------------------------------------
62 CommunicationKDP::~CommunicationKDP()
63 {
64     if (IsConnected())
65     {
66         Disconnect();
67     }
68 }
69 
70 bool
71 CommunicationKDP::SendRequestPacket (const PacketStreamType &request_packet)
72 {
73     Mutex::Locker locker(m_sequence_mutex);
74     return SendRequestPacketNoLock (request_packet);
75 }
76 
77 #if 0
78 typedef struct {
79 	uint8_t     request;	// Either: CommandType | ePacketTypeRequest, or CommandType | ePacketTypeReply
80 	uint8_t     sequence;
81 	uint16_t    length;		// Length of entire packet including this header
82 	uint32_t	key;		// Session key
83 } kdp_hdr_t;
84 #endif
85 
86 void
87 CommunicationKDP::MakeRequestPacketHeader (CommandType request_type,
88                                            PacketStreamType &request_packet,
89                                            uint16_t request_length)
90 {
91     request_packet.Clear();
92     request_packet.PutHex8 (request_type | ePacketTypeRequest); // Set the request type
93     request_packet.PutHex8 (m_request_sequence_id++);           // Sequence number
94     request_packet.PutHex16 (request_length);                   // Length of the packet including this header
95     request_packet.PutHex32 (m_session_key);                    // Session key
96 }
97 
98 bool
99 CommunicationKDP::SendRequestAndGetReply (const CommandType command,
100                                           const uint8_t request_sequence_id,
101                                           const PacketStreamType &request_packet,
102                                           DataExtractor &reply_packet)
103 {
104     if (IsRunning())
105     {
106         LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
107         if (log)
108         {
109             PacketStreamType log_strm;
110             DumpPacket (log_strm, request_packet.GetData(), request_packet.GetSize());
111             log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
112         }
113         return false;
114     }
115 
116     Mutex::Locker locker(m_sequence_mutex);
117 #ifdef LLDB_CONFIGURATION_DEBUG
118     // NOTE: this only works for packets that are in native endian byte order
119     assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2)));
120 #endif
121     if (SendRequestPacketNoLock(request_packet))
122     {
123         if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
124         {
125             uint32_t offset = 0;
126             const uint8_t reply_command = reply_packet.GetU8 (&offset);
127             const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
128             if ((reply_command & eCommandTypeMask) == command)
129             {
130                 if (request_sequence_id == reply_sequence_id)
131                 {
132                     if (command == KDP_RESUMECPUS)
133                         m_is_running.SetValue(true, eBroadcastAlways);
134                     return true;
135                 }
136             }
137         }
138     }
139     reply_packet.Clear();
140     return false;
141 }
142 
143 bool
144 CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packet)
145 {
146     if (IsConnected())
147     {
148         const char *packet_data = request_packet.GetData();
149         const size_t packet_size = request_packet.GetSize();
150 
151         LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
152         if (log)
153         {
154             PacketStreamType log_strm;
155             DumpPacket (log_strm, packet_data, packet_size);
156             log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
157         }
158         ConnectionStatus status = eConnectionStatusSuccess;
159 
160         size_t bytes_written = Write (packet_data,
161                                       packet_size,
162                                       status,
163                                       NULL);
164 
165         if (bytes_written == packet_size)
166             return true;
167 
168         if (log)
169             log->Printf ("error: failed to send packet entire packet %llu of %llu bytes sent", (uint64_t)bytes_written, (uint64_t)packet_size);
170     }
171     return false;
172 }
173 
174 bool
175 CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker)
176 {
177     return locker.TryLock (m_sequence_mutex);
178 }
179 
180 
181 bool
182 CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
183 {
184     return m_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
185 }
186 
187 size_t
188 CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &packet, uint32_t timeout_usec)
189 {
190     Mutex::Locker locker(m_sequence_mutex);
191     return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
192 }
193 
194 size_t
195 CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec)
196 {
197     uint8_t buffer[8192];
198     Error error;
199 
200     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
201 
202     // Check for a packet from our cache first without trying any reading...
203     if (CheckForPacket (NULL, 0, packet))
204         return packet.GetByteSize();
205 
206     bool timed_out = false;
207     while (IsConnected() && !timed_out)
208     {
209         lldb::ConnectionStatus status = eConnectionStatusNoConnection;
210         size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
211 
212         if (log)
213             log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %llu",
214                          __PRETTY_FUNCTION__,
215                          timeout_usec,
216                          Communication::ConnectionStatusAsCString (status),
217                          error.AsCString(),
218                          (uint64_t)bytes_read);
219 
220         if (bytes_read > 0)
221         {
222             if (CheckForPacket (buffer, bytes_read, packet))
223                 return packet.GetByteSize();
224         }
225         else
226         {
227             switch (status)
228             {
229             case eConnectionStatusTimedOut:
230                 timed_out = true;
231                 break;
232             case eConnectionStatusSuccess:
233                 //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
234                 break;
235 
236             case eConnectionStatusEndOfFile:
237             case eConnectionStatusNoConnection:
238             case eConnectionStatusLostConnection:
239             case eConnectionStatusError:
240                 Disconnect();
241                 break;
242             }
243         }
244     }
245     packet.Clear ();
246     return 0;
247 }
248 
249 bool
250 CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet)
251 {
252     // Put the packet data into the buffer in a thread safe fashion
253     Mutex::Locker locker(m_bytes_mutex);
254 
255     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
256 
257     if (src && src_len > 0)
258     {
259         if (log && log->GetVerbose())
260         {
261             PacketStreamType log_strm;
262             DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS);
263             log->Printf ("CommunicationKDP::%s adding %u bytes: %s",
264                          __FUNCTION__,
265                          (uint32_t)src_len,
266                          log_strm.GetData());
267         }
268         m_bytes.append ((const char *)src, src_len);
269     }
270 
271     // Make sure we at least have enough bytes for a packet header
272     const size_t bytes_available = m_bytes.size();
273     if (bytes_available >= 8)
274     {
275         packet.SetData (&m_bytes[0], bytes_available, m_byte_order);
276         uint32_t offset = 0;
277         uint8_t reply_command = packet.GetU8(&offset);
278         switch (reply_command)
279         {
280         case ePacketTypeRequest | KDP_EXCEPTION:
281         case ePacketTypeRequest | KDP_TERMINATION:
282             // We got an exception request, so be sure to send an ACK
283             {
284                 PacketStreamType request_ack_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
285                 // Set the reply but and make the ACK packet
286                 request_ack_packet.PutHex8 (reply_command | ePacketTypeReply);
287                 request_ack_packet.PutHex8 (packet.GetU8(&offset));
288                 request_ack_packet.PutHex16 (packet.GetU16(&offset));
289                 request_ack_packet.PutHex32 (packet.GetU32(&offset));
290                 m_is_running.SetValue(false, eBroadcastAlways);
291                 // Ack to the exception or termination
292                 SendRequestPacketNoLock (request_ack_packet);
293             }
294             // Fall through to case below to get packet contents
295         case ePacketTypeReply | KDP_CONNECT:
296         case ePacketTypeReply | KDP_DISCONNECT:
297         case ePacketTypeReply | KDP_HOSTINFO:
298         case ePacketTypeReply | KDP_VERSION:
299         case ePacketTypeReply | KDP_MAXBYTES:
300         case ePacketTypeReply | KDP_READMEM:
301         case ePacketTypeReply | KDP_WRITEMEM:
302         case ePacketTypeReply | KDP_READREGS:
303         case ePacketTypeReply | KDP_WRITEREGS:
304         case ePacketTypeReply | KDP_LOAD:
305         case ePacketTypeReply | KDP_IMAGEPATH:
306         case ePacketTypeReply | KDP_SUSPEND:
307         case ePacketTypeReply | KDP_RESUMECPUS:
308         case ePacketTypeReply | KDP_BREAKPOINT_SET:
309         case ePacketTypeReply | KDP_BREAKPOINT_REMOVE:
310         case ePacketTypeReply | KDP_REGIONS:
311         case ePacketTypeReply | KDP_REATTACH:
312         case ePacketTypeReply | KDP_HOSTREBOOT:
313         case ePacketTypeReply | KDP_READMEM64:
314         case ePacketTypeReply | KDP_WRITEMEM64:
315         case ePacketTypeReply | KDP_BREAKPOINT_SET64:
316         case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64:
317         case ePacketTypeReply | KDP_KERNELVERSION:
318             {
319                 offset = 2;
320                 const uint16_t length = packet.GetU16 (&offset);
321                 if (length <= bytes_available)
322                 {
323                     // We have an entire packet ready, we need to copy the data
324                     // bytes into a buffer that will be owned by the packet and
325                     // erase the bytes from our communcation buffer "m_bytes"
326                     packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length)));
327                     m_bytes.erase (0, length);
328 
329                     if (log)
330                     {
331                         PacketStreamType log_strm;
332                         DumpPacket (log_strm, packet);
333 
334                         log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
335                     }
336                     return true;
337                 }
338             }
339             break;
340 
341         default:
342             // Unrecognized reply command byte, erase this byte and try to get back on track
343             if (log)
344                 log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
345                              __FUNCTION__,
346                              (uint8_t)m_bytes[0]);
347             m_bytes.erase(0, 1);
348             break;
349         }
350     }
351     packet.Clear();
352     return false;
353 }
354 
355 
356 bool
357 CommunicationKDP::SendRequestConnect (uint16_t reply_port,
358                                       uint16_t exc_port,
359                                       const char *greeting)
360 {
361     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
362     if (greeting == NULL)
363         greeting = "";
364 
365     const CommandType command = KDP_CONNECT;
366     // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL
367     const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
368     const uint32_t request_sequence_id = m_request_sequence_id;
369     MakeRequestPacketHeader (command, request_packet, command_length);
370     // Always send connect ports as little endian
371     request_packet.SetByteOrder (eByteOrderLittle);
372     request_packet.PutHex16 (reply_port);
373     request_packet.PutHex16 (exc_port);
374     request_packet.SetByteOrder (m_byte_order);
375     request_packet.PutCString (greeting);
376     DataExtractor reply_packet;
377     return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
378 }
379 
380 void
381 CommunicationKDP::ClearKDPSettings ()
382 {
383     m_request_sequence_id = 0;
384     m_kdp_version_version = 0;
385     m_kdp_version_feature = 0;
386     m_kdp_hostinfo_cpu_mask = 0;
387     m_kdp_hostinfo_cpu_type = 0;
388     m_kdp_hostinfo_cpu_subtype = 0;
389 }
390 
391 bool
392 CommunicationKDP::SendRequestReattach (uint16_t reply_port)
393 {
394     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
395     const CommandType command = KDP_REATTACH;
396     // Length is 8 bytes for the header plus 2 bytes for the reply UDP port
397     const uint32_t command_length = 8 + 2;
398     const uint32_t request_sequence_id = m_request_sequence_id;
399     MakeRequestPacketHeader (command, request_packet, command_length);
400     // Always send connect ports as little endian
401     request_packet.SetByteOrder (eByteOrderLittle);
402     request_packet.PutHex16(reply_port);
403     request_packet.SetByteOrder (m_byte_order);
404     DataExtractor reply_packet;
405     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
406     {
407         // Reset the sequence ID to zero for reattach
408         ClearKDPSettings ();
409         uint32_t offset = 4;
410         m_session_key = reply_packet.GetU32 (&offset);
411         return true;
412     }
413     return false;
414 }
415 
416 uint32_t
417 CommunicationKDP::GetVersion ()
418 {
419     if (!VersionIsValid())
420         SendRequestVersion();
421     return m_kdp_version_version;
422 }
423 
424 uint32_t
425 CommunicationKDP::GetFeatureFlags ()
426 {
427     if (!VersionIsValid())
428         SendRequestVersion();
429     return m_kdp_version_feature;
430 }
431 
432 bool
433 CommunicationKDP::SendRequestVersion ()
434 {
435     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
436     const CommandType command = KDP_VERSION;
437     const uint32_t command_length = 8;
438     const uint32_t request_sequence_id = m_request_sequence_id;
439     MakeRequestPacketHeader (command, request_packet, command_length);
440     DataExtractor reply_packet;
441     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
442     {
443         uint32_t offset = 8;
444         m_kdp_version_version = reply_packet.GetU32 (&offset);
445         m_kdp_version_feature = reply_packet.GetU32 (&offset);
446         return true;
447     }
448     return false;
449 }
450 
451 #if 0 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...
452 const char *
453 CommunicationKDP::GetImagePath ()
454 {
455     if (m_image_path.empty())
456         SendRequestImagePath();
457     return m_image_path.c_str();
458 }
459 
460 bool
461 CommunicationKDP::SendRequestImagePath ()
462 {
463     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
464     const CommandType command = KDP_IMAGEPATH;
465     const uint32_t command_length = 8;
466     const uint32_t request_sequence_id = m_request_sequence_id;
467     MakeRequestPacketHeader (command, request_packet, command_length);
468     DataExtractor reply_packet;
469     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
470     {
471         const char *path = reply_packet.PeekCStr(8);
472         if (path && path[0])
473             m_kernel_version.assign (path);
474         return true;
475     }
476     return false;
477 }
478 #endif
479 
480 uint32_t
481 CommunicationKDP::GetCPUMask ()
482 {
483     if (!HostInfoIsValid())
484         SendRequestHostInfo();
485     return m_kdp_hostinfo_cpu_mask;
486 }
487 
488 uint32_t
489 CommunicationKDP::GetCPUType ()
490 {
491     if (!HostInfoIsValid())
492         SendRequestHostInfo();
493     return m_kdp_hostinfo_cpu_type;
494 }
495 
496 uint32_t
497 CommunicationKDP::GetCPUSubtype ()
498 {
499     if (!HostInfoIsValid())
500         SendRequestHostInfo();
501     return m_kdp_hostinfo_cpu_subtype;
502 }
503 
504 lldb_private::UUID
505 CommunicationKDP::GetUUID ()
506 {
507     UUID uuid;
508     if (GetKernelVersion() == NULL)
509         return uuid;
510 
511     if (m_kernel_version.find("UUID=") == std::string::npos)
512         return uuid;
513 
514     size_t p = m_kernel_version.find("UUID=") + strlen ("UUID=");
515     std::string uuid_str = m_kernel_version.substr(p, 36);
516     if (uuid_str.size() < 32)
517         return uuid;
518 
519     if (uuid.SetFromCString (uuid_str.c_str()) == 0)
520     {
521         UUID invalid_uuid;
522         return invalid_uuid;
523     }
524 
525     return uuid;
526 }
527 
528 lldb::addr_t
529 CommunicationKDP::GetLoadAddress ()
530 {
531     if (GetKernelVersion() == NULL)
532         return LLDB_INVALID_ADDRESS;
533 
534     if (m_kernel_version.find("stext=") == std::string::npos)
535         return LLDB_INVALID_ADDRESS;
536     size_t p = m_kernel_version.find("stext=") + strlen ("stext=");
537     if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x')
538         return LLDB_INVALID_ADDRESS;
539 
540     addr_t kernel_load_address;
541     errno = 0;
542     kernel_load_address = ::strtoul (m_kernel_version.c_str() + p, NULL, 16);
543     if (errno != 0 || kernel_load_address == 0)
544         return LLDB_INVALID_ADDRESS;
545 
546     return kernel_load_address;
547 }
548 
549 bool
550 CommunicationKDP::SendRequestHostInfo ()
551 {
552     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
553     const CommandType command = KDP_HOSTINFO;
554     const uint32_t command_length = 8;
555     const uint32_t request_sequence_id = m_request_sequence_id;
556     MakeRequestPacketHeader (command, request_packet, command_length);
557     DataExtractor reply_packet;
558     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
559     {
560         uint32_t offset = 8;
561         m_kdp_hostinfo_cpu_mask     = reply_packet.GetU32 (&offset);
562         m_kdp_hostinfo_cpu_type     = reply_packet.GetU32 (&offset);
563         m_kdp_hostinfo_cpu_subtype  = reply_packet.GetU32 (&offset);
564 
565         ArchSpec kernel_arch;
566         kernel_arch.SetArchitecture (eArchTypeMachO,
567                                      m_kdp_hostinfo_cpu_type,
568                                      m_kdp_hostinfo_cpu_subtype);
569 
570         m_addr_byte_size = kernel_arch.GetAddressByteSize();
571         m_byte_order = kernel_arch.GetByteOrder();
572         return true;
573     }
574     return false;
575 }
576 
577 const char *
578 CommunicationKDP::GetKernelVersion ()
579 {
580     if (m_kernel_version.empty())
581         SendRequestKernelVersion ();
582     return m_kernel_version.c_str();
583 }
584 
585 bool
586 CommunicationKDP::SendRequestKernelVersion ()
587 {
588     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
589     const CommandType command = KDP_KERNELVERSION;
590     const uint32_t command_length = 8;
591     const uint32_t request_sequence_id = m_request_sequence_id;
592     MakeRequestPacketHeader (command, request_packet, command_length);
593     DataExtractor reply_packet;
594     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
595     {
596         const char *kernel_version_cstr = reply_packet.PeekCStr(8);
597         if (kernel_version_cstr && kernel_version_cstr[0])
598             m_kernel_version.assign (kernel_version_cstr);
599         return true;
600     }
601     return false;
602 }
603 
604 bool
605 CommunicationKDP::SendRequestDisconnect ()
606 {
607     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
608     const CommandType command = KDP_DISCONNECT;
609     const uint32_t command_length = 8;
610     const uint32_t request_sequence_id = m_request_sequence_id;
611     MakeRequestPacketHeader (command, request_packet, command_length);
612     DataExtractor reply_packet;
613     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
614     {
615         // Are we supposed to get a reply for disconnect?
616     }
617     ClearKDPSettings ();
618     return true;
619 }
620 
621 uint32_t
622 CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr,
623                                          void *dst,
624                                          uint32_t dst_len,
625                                          Error &error)
626 {
627     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
628     bool use_64 = (GetVersion() >= 11);
629     uint32_t command_addr_byte_size = use_64 ? 8 : 4;
630     const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM;
631     // Size is header + address size + uint32_t length
632     const uint32_t command_length = 8 + command_addr_byte_size + 4;
633     const uint32_t request_sequence_id = m_request_sequence_id;
634     MakeRequestPacketHeader (command, request_packet, command_length);
635     request_packet.PutMaxHex64 (addr, command_addr_byte_size);
636     request_packet.PutHex32 (dst_len);
637     DataExtractor reply_packet;
638     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
639     {
640         uint32_t offset = 8;
641         uint32_t kdp_error = reply_packet.GetU32 (&offset);
642         uint32_t src_len = reply_packet.GetByteSize() - 12;
643 
644         if (src_len > 0)
645         {
646             const void *src = reply_packet.GetData(&offset, src_len);
647             if (src)
648             {
649                 ::memcpy (dst, src, src_len);
650                 error.Clear();
651                 return src_len;
652             }
653         }
654         if (kdp_error)
655             error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error);
656         else
657             error.SetErrorString ("kdp read memory failed");
658     }
659     else
660     {
661         error.SetErrorString ("failed to send packet");
662     }
663     return 0;
664 }
665 
666 
667 uint32_t
668 CommunicationKDP::SendRequestWriteMemory (lldb::addr_t addr,
669                                           const void *src,
670                                           uint32_t src_len,
671                                           Error &error)
672 {
673     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
674     bool use_64 = (GetVersion() >= 11);
675     uint32_t command_addr_byte_size = use_64 ? 8 : 4;
676     const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM;
677     // Size is header + address size + uint32_t length
678     const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len;
679     const uint32_t request_sequence_id = m_request_sequence_id;
680     MakeRequestPacketHeader (command, request_packet, command_length);
681     request_packet.PutMaxHex64 (addr, command_addr_byte_size);
682     request_packet.PutHex32 (src_len);
683     request_packet.PutRawBytes(src, src_len);
684 
685     DataExtractor reply_packet;
686     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
687     {
688         uint32_t offset = 8;
689         uint32_t kdp_error = reply_packet.GetU32 (&offset);
690         if (kdp_error)
691             error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error);
692         else
693         {
694             error.Clear();
695             return src_len;
696         }
697     }
698     else
699     {
700         error.SetErrorString ("failed to send packet");
701     }
702     return 0;
703 }
704 
705 bool
706 CommunicationKDP::SendRawRequest (uint8_t command_byte,
707                                   const void *src,  // Raw packet payload bytes
708                                   uint32_t src_len, // Raw packet payload length
709                                   DataExtractor &reply_packet,
710                                   Error &error)
711 {
712     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
713     // Size is header + address size + uint32_t length
714     const uint32_t command_length = 8 + src_len;
715     const CommandType command = (CommandType)command_byte;
716     const uint32_t request_sequence_id = m_request_sequence_id;
717     MakeRequestPacketHeader (command, request_packet, command_length);
718     request_packet.PutRawBytes(src, src_len);
719 
720     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
721     {
722         uint32_t offset = 8;
723         uint32_t kdp_error = reply_packet.GetU32 (&offset);
724         if (kdp_error)
725             error.SetErrorStringWithFormat ("request packet 0x%8.8x failed (error %u)", command_byte, kdp_error);
726         else
727         {
728             error.Clear();
729             return true;
730         }
731     }
732     else
733     {
734         error.SetErrorString ("failed to send packet");
735     }
736     return false;
737 }
738 
739 
740 const char *
741 CommunicationKDP::GetCommandAsCString (uint8_t command)
742 {
743     switch (command)
744     {
745     case KDP_CONNECT:               return "KDP_CONNECT";
746     case KDP_DISCONNECT:            return "KDP_DISCONNECT";
747     case KDP_HOSTINFO:              return "KDP_HOSTINFO";
748     case KDP_VERSION:               return "KDP_VERSION";
749     case KDP_MAXBYTES:              return "KDP_MAXBYTES";
750     case KDP_READMEM:               return "KDP_READMEM";
751     case KDP_WRITEMEM:              return "KDP_WRITEMEM";
752     case KDP_READREGS:              return "KDP_READREGS";
753     case KDP_WRITEREGS:             return "KDP_WRITEREGS";
754     case KDP_LOAD:                  return "KDP_LOAD";
755     case KDP_IMAGEPATH:             return "KDP_IMAGEPATH";
756     case KDP_SUSPEND:               return "KDP_SUSPEND";
757     case KDP_RESUMECPUS:            return "KDP_RESUMECPUS";
758     case KDP_EXCEPTION:             return "KDP_EXCEPTION";
759     case KDP_TERMINATION:           return "KDP_TERMINATION";
760     case KDP_BREAKPOINT_SET:        return "KDP_BREAKPOINT_SET";
761     case KDP_BREAKPOINT_REMOVE:     return "KDP_BREAKPOINT_REMOVE";
762     case KDP_REGIONS:               return "KDP_REGIONS";
763     case KDP_REATTACH:              return "KDP_REATTACH";
764     case KDP_HOSTREBOOT:            return "KDP_HOSTREBOOT";
765     case KDP_READMEM64:             return "KDP_READMEM64";
766     case KDP_WRITEMEM64:            return "KDP_WRITEMEM64";
767     case KDP_BREAKPOINT_SET64:      return "KDP_BREAKPOINT64_SET";
768     case KDP_BREAKPOINT_REMOVE64:   return "KDP_BREAKPOINT64_REMOVE";
769     case KDP_KERNELVERSION:         return "KDP_KERNELVERSION";
770     }
771     return NULL;
772 }
773 
774 void
775 CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len)
776 {
777     DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size);
778     DumpPacket (s, extractor);
779 }
780 
781 void
782 CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
783 {
784     const char *error_desc = NULL;
785     if (packet.GetByteSize() < 8)
786     {
787         error_desc = "error: invalid packet (too short): ";
788     }
789     else
790     {
791         uint32_t offset = 0;
792         const uint8_t first_packet_byte = packet.GetU8 (&offset);
793         const uint8_t sequence_id = packet.GetU8 (&offset);
794         const uint16_t length = packet.GetU16 (&offset);
795         const uint32_t key = packet.GetU32 (&offset);
796         const CommandType command = ExtractCommand (first_packet_byte);
797         const char *command_name = GetCommandAsCString (command);
798         if (command_name)
799         {
800             const bool is_reply = ExtractIsReply(first_packet_byte);
801             s.Printf ("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ",
802                       IsRunning(),
803                       is_reply ? "<--" : "-->",
804                       command_name,
805                       first_packet_byte,
806                       sequence_id,
807                       length,
808                       key);
809 
810             if (is_reply)
811             {
812                 // Dump request reply packets
813                 switch (command)
814                 {
815                     // Commands that return a single 32 bit error
816                     case KDP_CONNECT:
817                     case KDP_WRITEMEM:
818                     case KDP_WRITEMEM64:
819                     case KDP_BREAKPOINT_SET:
820                     case KDP_BREAKPOINT_REMOVE:
821                     case KDP_BREAKPOINT_SET64:
822                     case KDP_BREAKPOINT_REMOVE64:
823                     case KDP_WRITEREGS:
824                     case KDP_LOAD:
825                         {
826                             const uint32_t error = packet.GetU32 (&offset);
827                             s.Printf(" (error=0x%8.8x)", error);
828                         }
829                         break;
830 
831                     case KDP_DISCONNECT:
832                     case KDP_REATTACH:
833                     case KDP_HOSTREBOOT:
834                     case KDP_SUSPEND:
835                     case KDP_RESUMECPUS:
836                     case KDP_EXCEPTION:
837                     case KDP_TERMINATION:
838                         // No return value for the reply, just the header to ack
839                         s.PutCString(" ()");
840                         break;
841 
842                     case KDP_HOSTINFO:
843                         {
844                             const uint32_t cpu_mask = packet.GetU32 (&offset);
845                             const uint32_t cpu_type = packet.GetU32 (&offset);
846                             const uint32_t cpu_subtype = packet.GetU32 (&offset);
847                             s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype);
848                         }
849                         break;
850 
851                     case KDP_VERSION:
852                         {
853                             const uint32_t version = packet.GetU32 (&offset);
854                             const uint32_t feature = packet.GetU32 (&offset);
855                             s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
856                         }
857                         break;
858 
859                     case KDP_REGIONS:
860                         {
861                             const uint32_t region_count = packet.GetU32 (&offset);
862                             s.Printf(" (count = %u", region_count);
863                             for (uint32_t i=0; i<region_count; ++i)
864                             {
865                                 const addr_t region_addr = packet.GetPointer (&offset);
866                                 const uint32_t region_size = packet.GetU32 (&offset);
867                                 const uint32_t region_prot = packet.GetU32 (&offset);
868                                 s.Printf("\n\tregion[%llu] = { range = [0x%16.16llx - 0x%16.16llx), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot));
869                             }
870                         }
871                         break;
872 
873                     case KDP_READMEM:
874                     case KDP_READMEM64:
875                         {
876                             const uint32_t error = packet.GetU32 (&offset);
877                             const uint32_t count = packet.GetByteSize() - offset;
878                             s.Printf(" (error = 0x%8.8x:\n", error);
879                             if (count > 0)
880                                 packet.Dump (&s,                        // Stream to dump to
881                                              offset,                    // Offset within "packet"
882                                              eFormatBytesWithASCII,     // Format to use
883                                              1,                         // Size of each item in bytes
884                                              count,                     // Number of items
885                                              16,                        // Number per line
886                                              m_last_read_memory_addr,   // Don't show addresses before each line
887                                              0, 0);                     // No bitfields
888                         }
889                         break;
890 
891                     case KDP_READREGS:
892                         {
893                             const uint32_t error = packet.GetU32 (&offset);
894                             const uint32_t count = packet.GetByteSize() - offset;
895                             s.Printf(" (error = 0x%8.8x regs:\n", error);
896                             if (count > 0)
897                                 packet.Dump (&s,                        // Stream to dump to
898                                              offset,                    // Offset within "packet"
899                                              eFormatHex,                // Format to use
900                                              m_addr_byte_size,          // Size of each item in bytes
901                                              count / m_addr_byte_size,  // Number of items
902                                              16 / m_addr_byte_size,     // Number per line
903                                              LLDB_INVALID_ADDRESS,      // Don't show addresses before each line
904                                              0, 0);                     // No bitfields
905                         }
906                         break;
907 
908                     case KDP_KERNELVERSION:
909                         {
910                             const char *kernel_version = packet.PeekCStr(8);
911                             s.Printf(" (version = \"%s\")", kernel_version);
912                         }
913                         break;
914 
915                     case KDP_MAXBYTES:
916                         {
917                             const uint32_t max_bytes = packet.GetU32 (&offset);
918                             s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes);
919                         }
920                         break;
921                     case KDP_IMAGEPATH:
922                         {
923                             const char *path = packet.GetCStr(&offset);
924                             s.Printf(" (path = \"%s\")", path);
925                         }
926                         break;
927                     default:
928                         s.Printf(" (add support for dumping this packet reply!!!");
929                         break;
930 
931                 }
932             }
933             else
934             {
935                 // Dump request packets
936                 switch (command)
937                 {
938                     case KDP_CONNECT:
939                         {
940                             const uint16_t reply_port = packet.GetU16 (&offset);
941                             const uint16_t exc_port = packet.GetU16 (&offset);
942                             s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset));
943                         }
944                         break;
945 
946                     case KDP_DISCONNECT:
947                     case KDP_HOSTREBOOT:
948                     case KDP_HOSTINFO:
949                     case KDP_VERSION:
950                     case KDP_REGIONS:
951                     case KDP_KERNELVERSION:
952                     case KDP_MAXBYTES:
953                     case KDP_IMAGEPATH:
954                     case KDP_SUSPEND:
955                         // No args, just the header in the request...
956                         s.PutCString(" ()");
957                         break;
958 
959                     case KDP_RESUMECPUS:
960                         {
961                             const uint32_t cpu_mask = packet.GetU32 (&offset);
962                             s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask);
963                         }
964                         break;
965 
966                     case KDP_READMEM:
967                         {
968                             const uint32_t addr = packet.GetU32 (&offset);
969                             const uint32_t size = packet.GetU32 (&offset);
970                             s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size);
971                             m_last_read_memory_addr = addr;
972                         }
973                         break;
974 
975                     case KDP_WRITEMEM:
976                         {
977                             const uint32_t addr = packet.GetU32 (&offset);
978                             const uint32_t size = packet.GetU32 (&offset);
979                             s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size);
980                             if (size > 0)
981                                 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
982                         }
983                         break;
984 
985                     case KDP_READMEM64:
986                         {
987                             const uint64_t addr = packet.GetU64 (&offset);
988                             const uint32_t size = packet.GetU32 (&offset);
989                             s.Printf(" (addr = 0x%16.16llx, size = %u)", addr, size);
990                             m_last_read_memory_addr = addr;
991                         }
992                         break;
993 
994                     case KDP_WRITEMEM64:
995                         {
996                             const uint64_t addr = packet.GetU64 (&offset);
997                             const uint32_t size = packet.GetU32 (&offset);
998                             s.Printf(" (addr = 0x%16.16llx, size = %u, bytes = \n", addr, size);
999                             if (size > 0)
1000                                 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
1001                         }
1002                         break;
1003 
1004                     case KDP_READREGS:
1005                         {
1006                             const uint32_t cpu = packet.GetU32 (&offset);
1007                             const uint32_t flavor = packet.GetU32 (&offset);
1008                             s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor);
1009                         }
1010                         break;
1011 
1012                     case KDP_WRITEREGS:
1013                         {
1014                             const uint32_t cpu = packet.GetU32 (&offset);
1015                             const uint32_t flavor = packet.GetU32 (&offset);
1016                             const uint32_t nbytes = packet.GetByteSize() - offset;
1017                             s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor);
1018                             if (nbytes > 0)
1019                                 packet.Dump (&s,                        // Stream to dump to
1020                                              offset,                    // Offset within "packet"
1021                                              eFormatHex,                // Format to use
1022                                              m_addr_byte_size,          // Size of each item in bytes
1023                                              nbytes / m_addr_byte_size, // Number of items
1024                                              16 / m_addr_byte_size,     // Number per line
1025                                              LLDB_INVALID_ADDRESS,      // Don't show addresses before each line
1026                                              0, 0);                     // No bitfields
1027                         }
1028                         break;
1029 
1030 
1031                     case KDP_BREAKPOINT_SET:
1032                     case KDP_BREAKPOINT_REMOVE:
1033                         {
1034                             const uint32_t addr = packet.GetU32 (&offset);
1035                             s.Printf(" (addr = 0x%8.8x)", addr);
1036                         }
1037                         break;
1038 
1039                     case KDP_BREAKPOINT_SET64:
1040                     case KDP_BREAKPOINT_REMOVE64:
1041                         {
1042                             const uint64_t addr = packet.GetU64 (&offset);
1043                             s.Printf(" (addr = 0x%16.16llx)", addr);
1044                         }
1045                         break;
1046 
1047 
1048                     case KDP_LOAD:
1049                         {
1050                             const char *path = packet.GetCStr(&offset);
1051                             s.Printf(" (path = \"%s\")", path);
1052                         }
1053                         break;
1054 
1055                     case KDP_EXCEPTION:
1056                         {
1057                             const uint32_t count = packet.GetU32 (&offset);
1058 
1059                             for (uint32_t i=0; i<count; ++i)
1060                             {
1061                                 const uint32_t cpu = packet.GetU32 (&offset);
1062                                 const uint32_t exc = packet.GetU32 (&offset);
1063                                 const uint32_t code = packet.GetU32 (&offset);
1064                                 const uint32_t subcode = packet.GetU32 (&offset);
1065                                 const char *exc_cstr = NULL;
1066                                 switch (exc)
1067                                 {
1068                                     case 1:  exc_cstr = "EXC_BAD_ACCESS"; break;
1069                                     case 2:  exc_cstr = "EXC_BAD_INSTRUCTION"; break;
1070                                     case 3:  exc_cstr = "EXC_ARITHMETIC"; break;
1071                                     case 4:  exc_cstr = "EXC_EMULATION"; break;
1072                                     case 5:  exc_cstr = "EXC_SOFTWARE"; break;
1073                                     case 6:  exc_cstr = "EXC_BREAKPOINT"; break;
1074                                     case 7:  exc_cstr = "EXC_SYSCALL"; break;
1075                                     case 8:  exc_cstr = "EXC_MACH_SYSCALL"; break;
1076                                     case 9:  exc_cstr = "EXC_RPC_ALERT"; break;
1077                                     case 10: exc_cstr = "EXC_CRASH"; break;
1078                                     default:
1079                                         break;
1080                                 }
1081 
1082                                 s.Printf ("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)} ",
1083                                           cpu, exc_cstr, exc, code, code, subcode, subcode);
1084                             }
1085                         }
1086                         break;
1087 
1088                     case KDP_TERMINATION:
1089                         {
1090                             const uint32_t term_code = packet.GetU32 (&offset);
1091                             const uint32_t exit_code = packet.GetU32 (&offset);
1092                             s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code);
1093                         }
1094                         break;
1095 
1096                     case KDP_REATTACH:
1097                         {
1098                             const uint16_t reply_port = packet.GetU16 (&offset);
1099                             s.Printf(" (reply_port = %u)", reply_port);
1100                         }
1101                         break;
1102                 }
1103             }
1104         }
1105         else
1106         {
1107             error_desc = "error: invalid packet command: ";
1108         }
1109     }
1110 
1111     if (error_desc)
1112     {
1113         s.PutCString (error_desc);
1114 
1115         packet.Dump (&s,                    // Stream to dump to
1116                      0,                     // Offset into "packet"
1117                      eFormatBytes,          // Dump as hex bytes
1118                      1,                     // Size of each item is 1 for single bytes
1119                      packet.GetByteSize(),  // Number of bytes
1120                      UINT32_MAX,            // Num bytes per line
1121                      LLDB_INVALID_ADDRESS,  // Base address
1122                      0, 0);                 // Bitfield info set to not do anything bitfield related
1123     }
1124 }
1125 
1126 uint32_t
1127 CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
1128                                             uint32_t flavor,
1129                                             void *dst,
1130                                             uint32_t dst_len,
1131                                             Error &error)
1132 {
1133     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1134     const CommandType command = KDP_READREGS;
1135     // Size is header + 4 byte cpu and 4 byte flavor
1136     const uint32_t command_length = 8 + 4 + 4;
1137     const uint32_t request_sequence_id = m_request_sequence_id;
1138     MakeRequestPacketHeader (command, request_packet, command_length);
1139     request_packet.PutHex32 (cpu);
1140     request_packet.PutHex32 (flavor);
1141     DataExtractor reply_packet;
1142     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1143     {
1144         uint32_t offset = 8;
1145         uint32_t kdp_error = reply_packet.GetU32 (&offset);
1146         uint32_t src_len = reply_packet.GetByteSize() - 12;
1147 
1148         if (src_len > 0)
1149         {
1150             const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
1151             const void *src = reply_packet.GetData(&offset, bytes_to_copy);
1152             if (src)
1153             {
1154                 ::memcpy (dst, src, bytes_to_copy);
1155                 error.Clear();
1156                 // Return the number of bytes we could have returned regardless if
1157                 // we copied them or not, just so we know when things don't match up
1158                 return src_len;
1159             }
1160         }
1161         if (kdp_error)
1162             error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
1163         else
1164             error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
1165     }
1166     else
1167     {
1168         error.SetErrorString ("failed to send packet");
1169     }
1170     return 0;
1171 }
1172 
1173 uint32_t
1174 CommunicationKDP::SendRequestWriteRegisters (uint32_t cpu,
1175                                              uint32_t flavor,
1176                                              const void *src,
1177                                              uint32_t src_len,
1178                                              Error &error)
1179 {
1180     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1181     const CommandType command = KDP_WRITEREGS;
1182     // Size is header + 4 byte cpu and 4 byte flavor
1183     const uint32_t command_length = 8 + 4 + 4 + src_len;
1184     const uint32_t request_sequence_id = m_request_sequence_id;
1185     MakeRequestPacketHeader (command, request_packet, command_length);
1186     request_packet.PutHex32 (cpu);
1187     request_packet.PutHex32 (flavor);
1188     request_packet.Write(src, src_len);
1189     DataExtractor reply_packet;
1190     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1191     {
1192         uint32_t offset = 8;
1193         uint32_t kdp_error = reply_packet.GetU32 (&offset);
1194         if (kdp_error == 0)
1195             return src_len;
1196         error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
1197     }
1198     else
1199     {
1200         error.SetErrorString ("failed to send packet");
1201     }
1202     return 0;
1203 }
1204 
1205 
1206 bool
1207 CommunicationKDP::SendRequestResume ()
1208 {
1209     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1210     const CommandType command = KDP_RESUMECPUS;
1211     const uint32_t command_length = 12;
1212     const uint32_t request_sequence_id = m_request_sequence_id;
1213     MakeRequestPacketHeader (command, request_packet, command_length);
1214     request_packet.PutHex32(GetCPUMask());
1215 
1216     DataExtractor reply_packet;
1217     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1218         return true;
1219     return false;
1220 }
1221 
1222 bool
1223 CommunicationKDP::SendRequestBreakpoint (bool set, addr_t addr)
1224 {
1225     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1226     bool use_64 = (GetVersion() >= 11);
1227     uint32_t command_addr_byte_size = use_64 ? 8 : 4;
1228     const CommandType command = set ? (use_64 ? KDP_BREAKPOINT_SET64    : KDP_BREAKPOINT_SET   ):
1229                                       (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE);
1230 
1231     const uint32_t command_length = 8 + command_addr_byte_size;
1232     const uint32_t request_sequence_id = m_request_sequence_id;
1233     MakeRequestPacketHeader (command, request_packet, command_length);
1234     request_packet.PutMaxHex64 (addr, command_addr_byte_size);
1235 
1236     DataExtractor reply_packet;
1237     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1238     {
1239         uint32_t offset = 8;
1240         uint32_t kdp_error = reply_packet.GetU32 (&offset);
1241         if (kdp_error == 0)
1242             return true;
1243     }
1244     return false;
1245 }
1246 
1247 bool
1248 CommunicationKDP::SendRequestSuspend ()
1249 {
1250     PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1251     const CommandType command = KDP_SUSPEND;
1252     const uint32_t command_length = 8;
1253     const uint32_t request_sequence_id = m_request_sequence_id;
1254     MakeRequestPacketHeader (command, request_packet, command_length);
1255     DataExtractor reply_packet;
1256     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1257         return true;
1258     return false;
1259 }
1260 
1261