blob: f84eec36840a4ffd3bfc2de97ac17606ef4d2877 [file] [log] [blame]
Greg Clayton269f91e2011-07-15 18:02:58 +00001//===-- CommunicationKDP.cpp ------------------------------------*- C++ -*-===//
Greg Clayton363be3f2011-07-15 03:27:12 +00002//
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 <limits.h>
15#include <string.h>
16
17// C++ Includes
Greg Clayton0fa51242011-07-19 03:57:15 +000018#include "llvm/Support/MachO.h"
19
Greg Clayton363be3f2011-07-15 03:27:12 +000020// Other libraries and framework includes
Greg Claytond52d00f2011-07-16 03:19:08 +000021#include "lldb/Core/DataBufferHeap.h"
Greg Clayton1e5b0212011-07-15 16:31:38 +000022#include "lldb/Core/DataExtractor.h"
Greg Clayton363be3f2011-07-15 03:27:12 +000023#include "lldb/Core/Log.h"
Greg Clayton0fa51242011-07-19 03:57:15 +000024#include "lldb/Core/State.h"
Greg Clayton363be3f2011-07-15 03:27:12 +000025#include "lldb/Host/FileSpec.h"
26#include "lldb/Host/Host.h"
27#include "lldb/Host/TimeValue.h"
28#include "lldb/Target/Process.h"
Greg Clayton363be3f2011-07-15 03:27:12 +000029
30// Project includes
31#include "ProcessKDPLog.h"
32
33#define DEBUGSERVER_BASENAME "debugserver"
34
35using namespace lldb;
36using namespace lldb_private;
37
38//----------------------------------------------------------------------
39// CommunicationKDP constructor
40//----------------------------------------------------------------------
41CommunicationKDP::CommunicationKDP (const char *comm_name) :
42 Communication(comm_name),
Greg Clayton0fa51242011-07-19 03:57:15 +000043 m_addr_byte_size (4),
Greg Claytond52d00f2011-07-16 03:19:08 +000044 m_byte_order (eByteOrderLittle),
Greg Clayton363be3f2011-07-15 03:27:12 +000045 m_packet_timeout (1),
46 m_sequence_mutex (Mutex::eMutexTypeRecursive),
47 m_public_is_running (false),
48 m_private_is_running (false),
Greg Claytond52d00f2011-07-16 03:19:08 +000049 m_session_key (0u),
50 m_request_sequence_id (0u),
51 m_exception_sequence_id (0u),
52 m_kdp_version_version (0u),
53 m_kdp_version_feature (0u),
54 m_kdp_hostinfo_cpu_mask (0u),
55 m_kdp_hostinfo_cpu_type (0u),
56 m_kdp_hostinfo_cpu_subtype (0u)
Greg Clayton363be3f2011-07-15 03:27:12 +000057{
58}
59
60//----------------------------------------------------------------------
61// Destructor
62//----------------------------------------------------------------------
63CommunicationKDP::~CommunicationKDP()
64{
65 if (IsConnected())
66 {
67 Disconnect();
68 }
69}
70
Greg Clayton1e5b0212011-07-15 16:31:38 +000071bool
Greg Claytond52d00f2011-07-16 03:19:08 +000072CommunicationKDP::SendRequestPacket (const PacketStreamType &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +000073{
74 Mutex::Locker locker(m_sequence_mutex);
Greg Clayton1e5b0212011-07-15 16:31:38 +000075 return SendRequestPacketNoLock (request_packet);
Greg Clayton363be3f2011-07-15 03:27:12 +000076}
77
Greg Claytond52d00f2011-07-16 03:19:08 +000078#if 0
79typedef struct {
80 uint8_t request; // Either: CommandType | ePacketTypeRequest, or CommandType | ePacketTypeReply
81 uint8_t sequence;
82 uint16_t length; // Length of entire packet including this header
83 uint32_t key; // Session key
84} kdp_hdr_t;
85#endif
86
Greg Clayton1e5b0212011-07-15 16:31:38 +000087void
Greg Claytond52d00f2011-07-16 03:19:08 +000088CommunicationKDP::MakeRequestPacketHeader (CommandType request_type,
89 PacketStreamType &request_packet,
90 uint16_t request_length)
Greg Clayton363be3f2011-07-15 03:27:12 +000091{
Greg Clayton1e5b0212011-07-15 16:31:38 +000092 request_packet.Clear();
Greg Claytond52d00f2011-07-16 03:19:08 +000093 request_packet.PutHex8 (request_type | ePacketTypeRequest); // Set the request type
94 request_packet.PutHex8 (m_request_sequence_id++); // Sequence number
95 request_packet.PutHex16 (request_length); // Length of the packet including this header
96 request_packet.PutHex32 (m_session_key); // Session key
Greg Clayton363be3f2011-07-15 03:27:12 +000097}
98
Greg Claytond52d00f2011-07-16 03:19:08 +000099bool
100CommunicationKDP::SendRequestAndGetReply (const CommandType command,
101 const uint8_t request_sequence_id,
102 const PacketStreamType &request_packet,
103 DataExtractor &reply_packet)
104{
105
106 Mutex::Locker locker(m_sequence_mutex);
107 if (SendRequestPacketNoLock(request_packet))
108 {
Greg Clayton8d2ea282011-07-17 20:36:25 +0000109 if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
Greg Claytond52d00f2011-07-16 03:19:08 +0000110 {
111 uint32_t offset = 0;
112 const uint8_t reply_command = reply_packet.GetU8 (&offset);
113 const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
114 if ((reply_command & eCommandTypeMask) == command)
115 {
116 if (request_sequence_id == reply_sequence_id)
117 return true;
118 }
119 }
120 }
121 reply_packet.Clear();
122 return false;
123}
Greg Clayton363be3f2011-07-15 03:27:12 +0000124
Greg Clayton1e5b0212011-07-15 16:31:38 +0000125bool
Greg Claytond52d00f2011-07-16 03:19:08 +0000126CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +0000127{
128 if (IsConnected())
129 {
Greg Clayton1e5b0212011-07-15 16:31:38 +0000130 const char *packet_data = request_packet.GetData();
131 const size_t packet_size = request_packet.GetSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000132
133 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
134 if (log)
Greg Clayton1e5b0212011-07-15 16:31:38 +0000135 {
Greg Clayton0fa51242011-07-19 03:57:15 +0000136 PacketStreamType log_strm;
137 DumpPacket (log_strm, packet_data, packet_size);
138 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton1e5b0212011-07-15 16:31:38 +0000139 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000140 ConnectionStatus status = eConnectionStatusSuccess;
Greg Clayton363be3f2011-07-15 03:27:12 +0000141
Greg Clayton1e5b0212011-07-15 16:31:38 +0000142 size_t bytes_written = Write (packet_data,
143 packet_size,
144 status,
145 NULL);
146
147 if (bytes_written == packet_size)
148 return true;
149
150 if (log)
151 log->Printf ("error: failed to send packet entire packet %zu of %zu bytes sent", bytes_written, packet_size);
152 }
153 return false;
Greg Clayton363be3f2011-07-15 03:27:12 +0000154}
155
156bool
157CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker)
158{
159 return locker.TryLock (m_sequence_mutex.GetMutex());
160}
161
162
163bool
164CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
165{
166 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
167}
168
169size_t
Greg Claytond52d00f2011-07-16 03:19:08 +0000170CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &packet, uint32_t timeout_usec)
Greg Clayton363be3f2011-07-15 03:27:12 +0000171{
172 Mutex::Locker locker(m_sequence_mutex);
173 return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
174}
175
176size_t
Greg Claytond52d00f2011-07-16 03:19:08 +0000177CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec)
Greg Clayton363be3f2011-07-15 03:27:12 +0000178{
179 uint8_t buffer[8192];
180 Error error;
181
182 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
183
184 // Check for a packet from our cache first without trying any reading...
185 if (CheckForPacket (NULL, 0, packet))
Greg Claytond52d00f2011-07-16 03:19:08 +0000186 return packet.GetByteSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000187
188 bool timed_out = false;
189 while (IsConnected() && !timed_out)
190 {
191 lldb::ConnectionStatus status;
192 size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
193
194 if (log)
195 log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu",
196 __PRETTY_FUNCTION__,
197 timeout_usec,
198 Communication::ConnectionStatusAsCString (status),
199 error.AsCString(),
200 bytes_read);
201
202 if (bytes_read > 0)
203 {
204 if (CheckForPacket (buffer, bytes_read, packet))
Greg Claytond52d00f2011-07-16 03:19:08 +0000205 return packet.GetByteSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000206 }
207 else
208 {
209 switch (status)
210 {
211 case eConnectionStatusTimedOut:
212 timed_out = true;
213 break;
214 case eConnectionStatusSuccess:
215 //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
216 break;
217
218 case eConnectionStatusEndOfFile:
219 case eConnectionStatusNoConnection:
220 case eConnectionStatusLostConnection:
221 case eConnectionStatusError:
222 Disconnect();
223 break;
224 }
225 }
226 }
227 packet.Clear ();
228 return 0;
229}
230
231bool
Greg Claytond52d00f2011-07-16 03:19:08 +0000232CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet)
Greg Clayton363be3f2011-07-15 03:27:12 +0000233{
234 // Put the packet data into the buffer in a thread safe fashion
235 Mutex::Locker locker(m_bytes_mutex);
236
237 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
238
239 if (src && src_len > 0)
240 {
241 if (log && log->GetVerbose())
242 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000243 PacketStreamType log_strm;
Greg Clayton8d2ea282011-07-17 20:36:25 +0000244 DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS);
Greg Claytond52d00f2011-07-16 03:19:08 +0000245 log->Printf ("CommunicationKDP::%s adding %u bytes: %s",
Greg Clayton363be3f2011-07-15 03:27:12 +0000246 __FUNCTION__,
247 (uint32_t)src_len,
Greg Claytond52d00f2011-07-16 03:19:08 +0000248 log_strm.GetData());
Greg Clayton363be3f2011-07-15 03:27:12 +0000249 }
250 m_bytes.append ((const char *)src, src_len);
251 }
252
Greg Claytond52d00f2011-07-16 03:19:08 +0000253 // Make sure we at least have enough bytes for a packet header
254 const size_t bytes_available = m_bytes.size();
255 if (bytes_available >= 8)
Greg Clayton363be3f2011-07-15 03:27:12 +0000256 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000257 packet.SetData (&m_bytes[0], bytes_available, m_byte_order);
258 uint32_t offset = 0;
259 uint8_t reply_command = packet.GetU8(&offset);
260 switch (reply_command)
261 {
262 case ePacketTypeReply | eCommandTypeConnect:
263 case ePacketTypeReply | eCommandTypeDisconnect:
264 case ePacketTypeReply | eCommandTypeHostInfo:
265 case ePacketTypeReply | eCommandTypeVersion:
266 case ePacketTypeReply | eCommandTypeMaxBytes:
267 case ePacketTypeReply | eCommandTypeReadMemory:
268 case ePacketTypeReply | eCommandTypeWriteMemory:
269 case ePacketTypeReply | eCommandTypeReadRegisters:
270 case ePacketTypeReply | eCommandTypeWriteRegisters:
271 case ePacketTypeReply | eCommandTypeLoad:
272 case ePacketTypeReply | eCommandTypeImagePath:
273 case ePacketTypeReply | eCommandTypeSuspend:
274 case ePacketTypeReply | eCommandTypeResume:
275 case ePacketTypeReply | eCommandTypeException:
276 case ePacketTypeReply | eCommandTypeTermination:
277 case ePacketTypeReply | eCommandTypeBreakpointSet:
278 case ePacketTypeReply | eCommandTypeBreakpointRemove:
279 case ePacketTypeReply | eCommandTypeRegions:
280 case ePacketTypeReply | eCommandTypeReattach:
281 case ePacketTypeReply | eCommandTypeHostReboot:
282 case ePacketTypeReply | eCommandTypeReadMemory64:
283 case ePacketTypeReply | eCommandTypeWriteMemory64:
284 case ePacketTypeReply | eCommandTypeBreakpointSet64:
285 case ePacketTypeReply | eCommandTypeBreakpointRemove64:
286 case ePacketTypeReply | eCommandTypeKernelVersion:
287 {
288 offset = 2;
289 const uint16_t length = packet.GetU16 (&offset);
290 if (length <= bytes_available)
291 {
292 // We have an entire packet ready, we need to copy the data
293 // bytes into a buffer that will be owned by the packet and
294 // erase the bytes from our communcation buffer "m_bytes"
295 packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length)));
296 m_bytes.erase (0, length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000297
298 if (log)
299 {
300 PacketStreamType log_strm;
Greg Clayton0fa51242011-07-19 03:57:15 +0000301 DumpPacket (log_strm, packet);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000302
Greg Clayton0fa51242011-07-19 03:57:15 +0000303 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton8d2ea282011-07-17 20:36:25 +0000304 }
Greg Claytond52d00f2011-07-16 03:19:08 +0000305 return true;
306 }
307 }
308 break;
309
310 default:
311 // Unrecognized reply command byte, erase this byte and try to get back on track
312 if (log)
313 log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
314 __FUNCTION__,
315 (uint8_t)m_bytes[0]);
316 m_bytes.erase(0, 1);
317 break;
318 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000319 }
320 packet.Clear();
321 return false;
322}
323
Greg Clayton1e5b0212011-07-15 16:31:38 +0000324
Greg Claytond52d00f2011-07-16 03:19:08 +0000325bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000326CommunicationKDP::SendRequestConnect (uint16_t reply_port,
327 uint16_t exc_port,
328 const char *greeting)
Greg Clayton1e5b0212011-07-15 16:31:38 +0000329{
Greg Clayton0fa51242011-07-19 03:57:15 +0000330 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000331 if (greeting == NULL)
332 greeting = "";
333
334 const CommandType command = eCommandTypeConnect;
Greg Clayton8d2ea282011-07-17 20:36:25 +0000335 // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL
336 const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
Greg Claytond52d00f2011-07-16 03:19:08 +0000337 const uint32_t request_sequence_id = m_request_sequence_id;
338 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000339 // Always send connect ports as little endian
340 request_packet.SetByteOrder (eByteOrderLittle);
341 request_packet.PutHex16 (reply_port);
342 request_packet.PutHex16 (exc_port);
343 request_packet.SetByteOrder (m_byte_order);
344 request_packet.PutCString (greeting);
Greg Claytond52d00f2011-07-16 03:19:08 +0000345 DataExtractor reply_packet;
346 return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
Greg Clayton1e5b0212011-07-15 16:31:38 +0000347}
348
Greg Claytond52d00f2011-07-16 03:19:08 +0000349void
350CommunicationKDP::ClearKDPSettings ()
351{
352 m_request_sequence_id = 0;
353 m_kdp_version_version = 0;
354 m_kdp_version_feature = 0;
355 m_kdp_hostinfo_cpu_mask = 0;
356 m_kdp_hostinfo_cpu_type = 0;
357 m_kdp_hostinfo_cpu_subtype = 0;
358}
359
360bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000361CommunicationKDP::SendRequestReattach (uint16_t reply_port)
Greg Claytond52d00f2011-07-16 03:19:08 +0000362{
Greg Clayton0fa51242011-07-19 03:57:15 +0000363 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000364 const CommandType command = eCommandTypeReattach;
365 // Length is 8 bytes for the header plus 2 bytes for the reply UDP port
366 const uint32_t command_length = 8 + 2;
367 const uint32_t request_sequence_id = m_request_sequence_id;
368 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000369 // Always send connect ports as little endian
370 request_packet.SetByteOrder (eByteOrderLittle);
Greg Claytond52d00f2011-07-16 03:19:08 +0000371 request_packet.PutHex16(reply_port);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000372 request_packet.SetByteOrder (m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000373 DataExtractor reply_packet;
374 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
375 {
376 // Reset the sequence ID to zero for reattach
377 ClearKDPSettings ();
378 uint32_t offset = 4;
379 m_session_key = reply_packet.GetU32 (&offset);
380 return true;
381 }
382 return false;
383}
384
385uint32_t
386CommunicationKDP::GetVersion ()
387{
388 if (!VersionIsValid())
389 SendRequestVersion();
390 return m_kdp_version_version;
391}
392
393uint32_t
394CommunicationKDP::GetFeatureFlags ()
395{
396 if (!VersionIsValid())
397 SendRequestVersion();
398 return m_kdp_version_feature;
399}
400
401bool
402CommunicationKDP::SendRequestVersion ()
403{
Greg Clayton0fa51242011-07-19 03:57:15 +0000404 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000405 const CommandType command = eCommandTypeVersion;
406 const uint32_t command_length = 8;
407 const uint32_t request_sequence_id = m_request_sequence_id;
408 MakeRequestPacketHeader (command, request_packet, command_length);
409 DataExtractor reply_packet;
410 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
411 {
412 // Reset the sequence ID to zero for reattach
413 uint32_t offset = 8;
414 m_kdp_version_version = reply_packet.GetU32 (&offset);
415 m_kdp_version_feature = reply_packet.GetU32 (&offset);
416 return true;
417 }
418 return false;
419}
420
421uint32_t
422CommunicationKDP::GetCPUMask ()
423{
424 if (!HostInfoIsValid())
425 SendRequestHostInfo();
426 return m_kdp_hostinfo_cpu_mask;
427}
428
429uint32_t
430CommunicationKDP::GetCPUType ()
431{
432 if (!HostInfoIsValid())
433 SendRequestHostInfo();
434 return m_kdp_hostinfo_cpu_type;
435}
436
437uint32_t
438CommunicationKDP::GetCPUSubtype ()
439{
440 if (!HostInfoIsValid())
441 SendRequestHostInfo();
442 return m_kdp_hostinfo_cpu_subtype;
443}
444
445bool
446CommunicationKDP::SendRequestHostInfo ()
447{
Greg Clayton0fa51242011-07-19 03:57:15 +0000448 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000449 const CommandType command = eCommandTypeHostInfo;
450 const uint32_t command_length = 8;
451 const uint32_t request_sequence_id = m_request_sequence_id;
452 MakeRequestPacketHeader (command, request_packet, command_length);
453 DataExtractor reply_packet;
454 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
455 {
456 // Reset the sequence ID to zero for reattach
457 uint32_t offset = 8;
Greg Clayton0fa51242011-07-19 03:57:15 +0000458 m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
459 m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
460 m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
461
462 ArchSpec kernel_arch;
463 kernel_arch.SetArchitecture (eArchTypeMachO,
464 m_kdp_hostinfo_cpu_type,
465 m_kdp_hostinfo_cpu_subtype);
466
467 m_addr_byte_size = kernel_arch.GetAddressByteSize();
468 m_byte_order = kernel_arch.GetByteOrder();
Greg Claytond52d00f2011-07-16 03:19:08 +0000469 return true;
470 }
471 return false;
472}
473
474bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000475CommunicationKDP::SendRequestDisconnect ()
Greg Clayton1e5b0212011-07-15 16:31:38 +0000476{
Greg Clayton0fa51242011-07-19 03:57:15 +0000477 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000478 const CommandType command = eCommandTypeDisconnect;
479 const uint32_t command_length = 8;
480 const uint32_t request_sequence_id = m_request_sequence_id;
481 MakeRequestPacketHeader (command, request_packet, command_length);
482 DataExtractor reply_packet;
483 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
484 {
485 // Are we supposed to get a reply for disconnect?
486 }
487 ClearKDPSettings ();
488 return true;
Greg Clayton1e5b0212011-07-15 16:31:38 +0000489}
490
Greg Clayton0fa51242011-07-19 03:57:15 +0000491uint32_t
492CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr,
493 void *dst,
494 uint32_t dst_len,
495 Error &error)
496{
497 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
498 bool use_64 = (GetVersion() >= 11);
499 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
500 const CommandType command = use_64 ? eCommandTypeReadMemory64 : eCommandTypeReadMemory;
501 // Size is header + address size + uint32_t length
502 const uint32_t command_length = 8 + command_addr_byte_size + 4;
503 const uint32_t request_sequence_id = m_request_sequence_id;
504 MakeRequestPacketHeader (command, request_packet, command_length);
505 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
506 request_packet.PutHex32 (dst_len);
507 DataExtractor reply_packet;
508 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
509 {
510 // Reset the sequence ID to zero for reattach
511 uint32_t offset = 8;
512 uint32_t kdp_error = reply_packet.GetU32 (&offset);
513 uint32_t src_len = reply_packet.GetByteSize() - 12;
514
515 if (src_len > 0)
516 {
517 const void *src = reply_packet.GetData(&offset, src_len);
518 if (src)
519 {
520 ::memcpy (dst, src, src_len);
521 error.Clear();
522 return src_len;
523 }
524 }
525 if (kdp_error)
526 error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error);
527 else
528 error.SetErrorString ("kdp read memory failed");
529 }
530 return 0;
531}
532
533const char *
534CommunicationKDP::GetCommandAsCString (uint8_t command)
535{
536 switch (command)
537 {
538 case eCommandTypeConnect: return "KDP_CONNECT";
539 case eCommandTypeDisconnect: return "KDP_DISCONNECT";
540 case eCommandTypeHostInfo: return "KDP_HOSTINFO";
541 case eCommandTypeVersion: return "KDP_VERSION";
542 case eCommandTypeMaxBytes: return "KDP_MAXBYTES";
543 case eCommandTypeReadMemory: return "KDP_READMEM";
544 case eCommandTypeWriteMemory: return "KDP_WRITEMEM";
545 case eCommandTypeReadRegisters: return "KDP_READREGS";
546 case eCommandTypeWriteRegisters: return "KDP_WRITEREGS";
547 case eCommandTypeLoad: return "KDP_LOAD";
548 case eCommandTypeImagePath: return "KDP_IMAGEPATH";
549 case eCommandTypeSuspend: return "KDP_SUSPEND";
550 case eCommandTypeResume: return "KDP_RESUMECPUS";
551 case eCommandTypeException: return "KDP_EXCEPTION";
552 case eCommandTypeTermination: return "KDP_TERMINATION";
553 case eCommandTypeBreakpointSet: return "KDP_BREAKPOINT_SET";
554 case eCommandTypeBreakpointRemove: return "KDP_BREAKPOINT_REMOVE";
555 case eCommandTypeRegions: return "KDP_REGIONS";
556 case eCommandTypeReattach: return "KDP_REATTACH";
557 case eCommandTypeHostReboot: return "KDP_HOSTREBOOT";
558 case eCommandTypeReadMemory64: return "KDP_READMEM64";
559 case eCommandTypeWriteMemory64: return "KDP_WRITEMEM64";
560 case eCommandTypeBreakpointSet64: return "KDP_BREAKPOINT64_SET";
561 case eCommandTypeBreakpointRemove64: return "KDP_BREAKPOINT64_REMOVE";
562 case eCommandTypeKernelVersion: return "KDP_KERNELVERSION";
563 }
564 return NULL;
565}
566
567void
568CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len)
569{
570 DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size);
571 DumpPacket (s, extractor);
572}
573
574void
575CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
576{
577 const char *error_desc = NULL;
578 if (packet.GetByteSize() < 8)
579 {
580 error_desc = "error: invalid packet (too short): ";
581 }
582 else
583 {
584 uint32_t offset = 0;
585 const uint8_t first_packet_byte = packet.GetU8 (&offset);
586 const uint8_t sequence_id = packet.GetU8 (&offset);
587 const uint16_t length = packet.GetU16 (&offset);
588 const uint32_t key = packet.GetU32 (&offset);
589 const CommandType command = ExtractCommand (first_packet_byte);
590 const char *command_name = GetCommandAsCString (command);
591 if (command_name)
592 {
593 const bool is_reply = ExtractIsReply(first_packet_byte);
594 s.Printf ("%s {%u:%u} <0x%4.4x> %s",
595 is_reply ? "<--" : "-->",
596 key,
597 sequence_id,
598 length,
599 command_name);
600
601 if (is_reply)
602 {
603 // Dump request reply packets
604 switch (command)
605 {
606 case eCommandTypeConnect:
607 {
608 const uint32_t error = packet.GetU32 (&offset);
609 s.Printf(" (error=0x%8.8x)", error);
610 }
611 break;
612
613 case eCommandTypeDisconnect:
614 case eCommandTypeReattach:
615 case eCommandTypeHostReboot:
616 // No return value for the reply, just the header to ack
617 break;
618
619 case eCommandTypeHostInfo:
620 {
621 const uint32_t cpu_mask = packet.GetU32 (&offset);
622 const uint32_t cpu_type = packet.GetU32 (&offset);
623 const uint32_t cpu_subtype = packet.GetU32 (&offset);
624 s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype);
625 }
626 break;
627
628 case eCommandTypeVersion:
629 {
630 const uint32_t version = packet.GetU32 (&offset);
631 const uint32_t feature = packet.GetU32 (&offset);
632 s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
633 }
634 break;
635
636 case eCommandTypeRegions:
637 {
638 const uint32_t region_count = packet.GetU32 (&offset);
639 s.Printf(" (count = %u", region_count);
640 for (uint32_t i=0; i<region_count; ++i)
641 {
642 const addr_t region_addr = packet.GetPointer (&offset);
643 const uint32_t region_size = packet.GetU32 (&offset);
644 const uint32_t region_prot = packet.GetU32 (&offset);
645 s.Printf("\n\tregion[%i] = { range = [0x%16.16llx - 0x%16.16llx), size = 0x%8.8x, prot = %s }", region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot));
646 }
647 }
648 break;
649
650 case eCommandTypeReadMemory:
651 case eCommandTypeReadMemory64:
652 case eCommandTypeReadRegisters:
653 {
654 const uint32_t error = packet.GetU32 (&offset);
655 const uint32_t count = packet.GetByteSize() - 12;
656 s.Printf(" (error = 0x%8.8x <0x%x>:\n", error, count);
657 if (count > 0)
658 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, count), count, 32, LLDB_INVALID_ADDRESS);
659 }
660 break;
661
662 case eCommandTypeMaxBytes:
663 case eCommandTypeWriteMemory:
664 case eCommandTypeWriteRegisters:
665 case eCommandTypeLoad:
666 case eCommandTypeImagePath:
667 case eCommandTypeSuspend:
668 case eCommandTypeResume:
669 case eCommandTypeException:
670 case eCommandTypeTermination:
671 case eCommandTypeBreakpointSet:
672 case eCommandTypeBreakpointRemove:
673 case eCommandTypeWriteMemory64:
674 case eCommandTypeBreakpointSet64:
675 case eCommandTypeBreakpointRemove64:
676 case eCommandTypeKernelVersion:
677 break;
678
679 }
680 }
681 else
682 {
683 // Dump request packets
684 switch (command)
685 {
686 case eCommandTypeConnect:
687 {
688 const uint16_t reply_port = packet.GetU16 (&offset);
689 const uint16_t exc_port = packet.GetU16 (&offset);
690 s.Printf(" (reply_port=%u, exc_port=%u, greeting=\"%s\")", reply_port, exc_port, packet.GetCStr(&offset));
691 }
692 break;
693
694 case eCommandTypeDisconnect:
695 case eCommandTypeHostReboot:
696 case eCommandTypeHostInfo:
697 case eCommandTypeVersion:
698 case eCommandTypeRegions:
699 // No args, just the header in the request...
700 break;
701
702 case eCommandTypeReadMemory:
703 {
704 const uint32_t addr = packet.GetU32 (&offset);
705 const uint32_t size = packet.GetU32 (&offset);
706 s.Printf(" (addr = 0x%8.8x, size=%u)", addr, size);
707 }
708 break;
709
710 case eCommandTypeReadMemory64:
711 {
712 const uint64_t addr = packet.GetU64 (&offset);
713 const uint32_t size = packet.GetU32 (&offset);
714 s.Printf(" (addr = 0x%16.16llx, size=%u)", addr, size);
715 }
716 break;
717
718 case eCommandTypeReadRegisters:
719 {
720 const uint32_t cpu = packet.GetU32 (&offset);
721 const uint32_t flavor = packet.GetU32 (&offset);
722 s.Printf(" (cpu = %u, flavor=%u)", cpu, flavor);
723 }
724 break;
725
726 case eCommandTypeMaxBytes:
727 case eCommandTypeWriteMemory:
728 case eCommandTypeWriteRegisters:
729 case eCommandTypeLoad:
730 case eCommandTypeImagePath:
731 case eCommandTypeSuspend:
732 case eCommandTypeResume:
733 case eCommandTypeException:
734 case eCommandTypeTermination:
735 case eCommandTypeBreakpointSet:
736 case eCommandTypeBreakpointRemove:
737 break;
738
739 case eCommandTypeReattach:
740 {
741 const uint16_t reply_port = packet.GetU16 (&offset);
742 s.Printf(" (reply_port=%u)", reply_port);
743 }
744 break;
745
746 case eCommandTypeWriteMemory64:
747 case eCommandTypeBreakpointSet64:
748 case eCommandTypeBreakpointRemove64:
749 case eCommandTypeKernelVersion:
750 break;
751 }
752 }
753 }
754 else
755 {
756 error_desc = "error: invalid packet command: ";
757 }
758 }
759
760 if (error_desc)
761 {
762 s.PutCString (error_desc);
763
764 packet.Dump (&s, // Stream to dump to
765 0, // Offset into "packet"
766 eFormatBytes, // Dump as hex bytes
767 1, // Size of each item is 1 for single bytes
768 packet.GetByteSize(), // Number of bytes
769 UINT32_MAX, // Num bytes per line
770 LLDB_INVALID_ADDRESS, // Base address
771 0, 0); // Bitfield info set to not do anything bitfield related
772 }
773}
774
775uint32_t
776CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
777 uint32_t flavor,
778 void *dst,
779 uint32_t dst_len,
780 Error &error)
781{
782 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
783 const CommandType command = eCommandTypeReadRegisters;
784 // Size is header + 4 byte cpu and 4 byte flavor
785 const uint32_t command_length = 8 + 4 + 4;
786 const uint32_t request_sequence_id = m_request_sequence_id;
787 MakeRequestPacketHeader (command, request_packet, command_length);
788 request_packet.PutHex32 (cpu);
789 request_packet.PutHex32 (flavor);
790 DataExtractor reply_packet;
791 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
792 {
793 // Reset the sequence ID to zero for reattach
794 uint32_t offset = 8;
795 uint32_t kdp_error = reply_packet.GetU32 (&offset);
796 uint32_t src_len = reply_packet.GetByteSize() - 12;
797
798 if (src_len > 0)
799 {
800 const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
801 const void *src = reply_packet.GetData(&offset, bytes_to_copy);
802 if (src)
803 {
804 ::memcpy (dst, src, bytes_to_copy);
805 error.Clear();
806 // Return the number of bytes we could have returned regardless if
807 // we copied them or not, just so we know when things don't match up
808 return src_len;
809 }
810 }
811 if (kdp_error)
812 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
813 else
814 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
815 }
816 return 0;
817}
818