blob: 48c65dbe799af4ce0c04f2c17345a2135841b185 [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
Greg Clayton363be3f2011-07-15 03:27:12 +000033using namespace lldb;
34using namespace lldb_private;
35
36//----------------------------------------------------------------------
37// CommunicationKDP constructor
38//----------------------------------------------------------------------
39CommunicationKDP::CommunicationKDP (const char *comm_name) :
40 Communication(comm_name),
Greg Clayton0fa51242011-07-19 03:57:15 +000041 m_addr_byte_size (4),
Greg Claytond52d00f2011-07-16 03:19:08 +000042 m_byte_order (eByteOrderLittle),
Greg Clayton363be3f2011-07-15 03:27:12 +000043 m_packet_timeout (1),
44 m_sequence_mutex (Mutex::eMutexTypeRecursive),
Greg Clayton363be3f2011-07-15 03:27:12 +000045 m_private_is_running (false),
Greg Claytond52d00f2011-07-16 03:19:08 +000046 m_session_key (0u),
47 m_request_sequence_id (0u),
48 m_exception_sequence_id (0u),
49 m_kdp_version_version (0u),
50 m_kdp_version_feature (0u),
51 m_kdp_hostinfo_cpu_mask (0u),
52 m_kdp_hostinfo_cpu_type (0u),
53 m_kdp_hostinfo_cpu_subtype (0u)
Greg Clayton363be3f2011-07-15 03:27:12 +000054{
55}
56
57//----------------------------------------------------------------------
58// Destructor
59//----------------------------------------------------------------------
60CommunicationKDP::~CommunicationKDP()
61{
62 if (IsConnected())
63 {
64 Disconnect();
65 }
66}
67
Greg Clayton1e5b0212011-07-15 16:31:38 +000068bool
Greg Claytond52d00f2011-07-16 03:19:08 +000069CommunicationKDP::SendRequestPacket (const PacketStreamType &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +000070{
71 Mutex::Locker locker(m_sequence_mutex);
Greg Clayton1e5b0212011-07-15 16:31:38 +000072 return SendRequestPacketNoLock (request_packet);
Greg Clayton363be3f2011-07-15 03:27:12 +000073}
74
Greg Claytond52d00f2011-07-16 03:19:08 +000075#if 0
76typedef struct {
77 uint8_t request; // Either: CommandType | ePacketTypeRequest, or CommandType | ePacketTypeReply
78 uint8_t sequence;
79 uint16_t length; // Length of entire packet including this header
80 uint32_t key; // Session key
81} kdp_hdr_t;
82#endif
83
Greg Clayton1e5b0212011-07-15 16:31:38 +000084void
Greg Claytond52d00f2011-07-16 03:19:08 +000085CommunicationKDP::MakeRequestPacketHeader (CommandType request_type,
86 PacketStreamType &request_packet,
87 uint16_t request_length)
Greg Clayton363be3f2011-07-15 03:27:12 +000088{
Greg Clayton1e5b0212011-07-15 16:31:38 +000089 request_packet.Clear();
Greg Claytond52d00f2011-07-16 03:19:08 +000090 request_packet.PutHex8 (request_type | ePacketTypeRequest); // Set the request type
91 request_packet.PutHex8 (m_request_sequence_id++); // Sequence number
92 request_packet.PutHex16 (request_length); // Length of the packet including this header
93 request_packet.PutHex32 (m_session_key); // Session key
Greg Clayton363be3f2011-07-15 03:27:12 +000094}
95
Greg Claytond52d00f2011-07-16 03:19:08 +000096bool
97CommunicationKDP::SendRequestAndGetReply (const CommandType command,
98 const uint8_t request_sequence_id,
99 const PacketStreamType &request_packet,
100 DataExtractor &reply_packet)
101{
102
103 Mutex::Locker locker(m_sequence_mutex);
104 if (SendRequestPacketNoLock(request_packet))
105 {
Greg Clayton8d2ea282011-07-17 20:36:25 +0000106 if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
Greg Claytond52d00f2011-07-16 03:19:08 +0000107 {
108 uint32_t offset = 0;
109 const uint8_t reply_command = reply_packet.GetU8 (&offset);
110 const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
111 if ((reply_command & eCommandTypeMask) == command)
112 {
113 if (request_sequence_id == reply_sequence_id)
114 return true;
115 }
116 }
117 }
118 reply_packet.Clear();
119 return false;
120}
Greg Clayton363be3f2011-07-15 03:27:12 +0000121
Greg Clayton1e5b0212011-07-15 16:31:38 +0000122bool
Greg Claytond52d00f2011-07-16 03:19:08 +0000123CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +0000124{
125 if (IsConnected())
126 {
Greg Clayton1e5b0212011-07-15 16:31:38 +0000127 const char *packet_data = request_packet.GetData();
128 const size_t packet_size = request_packet.GetSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000129
130 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
131 if (log)
Greg Clayton1e5b0212011-07-15 16:31:38 +0000132 {
Greg Clayton0fa51242011-07-19 03:57:15 +0000133 PacketStreamType log_strm;
134 DumpPacket (log_strm, packet_data, packet_size);
135 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton1e5b0212011-07-15 16:31:38 +0000136 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000137 ConnectionStatus status = eConnectionStatusSuccess;
Greg Clayton363be3f2011-07-15 03:27:12 +0000138
Greg Clayton1e5b0212011-07-15 16:31:38 +0000139 size_t bytes_written = Write (packet_data,
140 packet_size,
141 status,
142 NULL);
143
144 if (bytes_written == packet_size)
145 return true;
146
147 if (log)
Greg Clayton851e30e2012-09-18 18:04:04 +0000148 log->Printf ("error: failed to send packet entire packet %llu of %llu bytes sent", (uint64_t)bytes_written, (uint64_t)packet_size);
Greg Clayton1e5b0212011-07-15 16:31:38 +0000149 }
150 return false;
Greg Clayton363be3f2011-07-15 03:27:12 +0000151}
152
153bool
Greg Clayton516f0842012-04-11 00:24:49 +0000154CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker)
Greg Clayton363be3f2011-07-15 03:27:12 +0000155{
Jim Ingham1b584eb2012-05-04 23:02:50 +0000156 return locker.TryLock (m_sequence_mutex);
Greg Clayton363be3f2011-07-15 03:27:12 +0000157}
158
159
160bool
161CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
162{
163 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
164}
165
166size_t
Greg Claytond52d00f2011-07-16 03:19:08 +0000167CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &packet, uint32_t timeout_usec)
Greg Clayton363be3f2011-07-15 03:27:12 +0000168{
169 Mutex::Locker locker(m_sequence_mutex);
170 return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
171}
172
173size_t
Greg Claytond52d00f2011-07-16 03:19:08 +0000174CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec)
Greg Clayton363be3f2011-07-15 03:27:12 +0000175{
176 uint8_t buffer[8192];
177 Error error;
178
179 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
180
181 // Check for a packet from our cache first without trying any reading...
182 if (CheckForPacket (NULL, 0, packet))
Greg Claytond52d00f2011-07-16 03:19:08 +0000183 return packet.GetByteSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000184
185 bool timed_out = false;
186 while (IsConnected() && !timed_out)
187 {
Johnny Chen1e3a5222011-07-21 19:00:59 +0000188 lldb::ConnectionStatus status = eConnectionStatusNoConnection;
Greg Clayton363be3f2011-07-15 03:27:12 +0000189 size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
190
191 if (log)
Greg Clayton851e30e2012-09-18 18:04:04 +0000192 log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %llu",
Greg Clayton363be3f2011-07-15 03:27:12 +0000193 __PRETTY_FUNCTION__,
194 timeout_usec,
195 Communication::ConnectionStatusAsCString (status),
196 error.AsCString(),
Greg Clayton851e30e2012-09-18 18:04:04 +0000197 (uint64_t)bytes_read);
Greg Clayton363be3f2011-07-15 03:27:12 +0000198
199 if (bytes_read > 0)
200 {
201 if (CheckForPacket (buffer, bytes_read, packet))
Greg Claytond52d00f2011-07-16 03:19:08 +0000202 return packet.GetByteSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000203 }
204 else
205 {
206 switch (status)
207 {
208 case eConnectionStatusTimedOut:
209 timed_out = true;
210 break;
211 case eConnectionStatusSuccess:
212 //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
213 break;
214
215 case eConnectionStatusEndOfFile:
216 case eConnectionStatusNoConnection:
217 case eConnectionStatusLostConnection:
218 case eConnectionStatusError:
219 Disconnect();
220 break;
221 }
222 }
223 }
224 packet.Clear ();
225 return 0;
226}
227
228bool
Greg Claytond52d00f2011-07-16 03:19:08 +0000229CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet)
Greg Clayton363be3f2011-07-15 03:27:12 +0000230{
231 // Put the packet data into the buffer in a thread safe fashion
232 Mutex::Locker locker(m_bytes_mutex);
233
234 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
235
236 if (src && src_len > 0)
237 {
238 if (log && log->GetVerbose())
239 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000240 PacketStreamType log_strm;
Greg Clayton8d2ea282011-07-17 20:36:25 +0000241 DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS);
Greg Claytond52d00f2011-07-16 03:19:08 +0000242 log->Printf ("CommunicationKDP::%s adding %u bytes: %s",
Greg Clayton363be3f2011-07-15 03:27:12 +0000243 __FUNCTION__,
244 (uint32_t)src_len,
Greg Claytond52d00f2011-07-16 03:19:08 +0000245 log_strm.GetData());
Greg Clayton363be3f2011-07-15 03:27:12 +0000246 }
247 m_bytes.append ((const char *)src, src_len);
248 }
249
Greg Claytond52d00f2011-07-16 03:19:08 +0000250 // Make sure we at least have enough bytes for a packet header
251 const size_t bytes_available = m_bytes.size();
252 if (bytes_available >= 8)
Greg Clayton363be3f2011-07-15 03:27:12 +0000253 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000254 packet.SetData (&m_bytes[0], bytes_available, m_byte_order);
255 uint32_t offset = 0;
256 uint8_t reply_command = packet.GetU8(&offset);
257 switch (reply_command)
258 {
Greg Claytonea636012012-09-21 01:55:30 +0000259 case ePacketTypeRequest | KDP_EXCEPTION:
260 case ePacketTypeRequest | KDP_TERMINATION:
261 // We got an exception request, so be sure to send an ACK
262 {
263 PacketStreamType request_ack_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
264 // Set the reply but and make the ACK packet
265 request_ack_packet.PutHex8 (reply_command | ePacketTypeReply);
266 request_ack_packet.PutHex8 (packet.GetU8(&offset));
267 request_ack_packet.PutHex16 (packet.GetU16(&offset));
268 request_ack_packet.PutHex32 (packet.GetU32(&offset));
269 // Ack to the exception or termination
270 SendRequestPacketNoLock (request_ack_packet);
271 }
272 // Fall through to case below to get packet contents
Greg Clayton7b139222011-07-21 01:12:01 +0000273 case ePacketTypeReply | KDP_CONNECT:
274 case ePacketTypeReply | KDP_DISCONNECT:
275 case ePacketTypeReply | KDP_HOSTINFO:
276 case ePacketTypeReply | KDP_VERSION:
277 case ePacketTypeReply | KDP_MAXBYTES:
278 case ePacketTypeReply | KDP_READMEM:
279 case ePacketTypeReply | KDP_WRITEMEM:
280 case ePacketTypeReply | KDP_READREGS:
281 case ePacketTypeReply | KDP_WRITEREGS:
282 case ePacketTypeReply | KDP_LOAD:
283 case ePacketTypeReply | KDP_IMAGEPATH:
284 case ePacketTypeReply | KDP_SUSPEND:
285 case ePacketTypeReply | KDP_RESUMECPUS:
Greg Clayton7b139222011-07-21 01:12:01 +0000286 case ePacketTypeReply | KDP_BREAKPOINT_SET:
287 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE:
288 case ePacketTypeReply | KDP_REGIONS:
289 case ePacketTypeReply | KDP_REATTACH:
290 case ePacketTypeReply | KDP_HOSTREBOOT:
291 case ePacketTypeReply | KDP_READMEM64:
292 case ePacketTypeReply | KDP_WRITEMEM64:
293 case ePacketTypeReply | KDP_BREAKPOINT_SET64:
294 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64:
295 case ePacketTypeReply | KDP_KERNELVERSION:
Greg Claytond52d00f2011-07-16 03:19:08 +0000296 {
297 offset = 2;
298 const uint16_t length = packet.GetU16 (&offset);
299 if (length <= bytes_available)
300 {
301 // We have an entire packet ready, we need to copy the data
302 // bytes into a buffer that will be owned by the packet and
303 // erase the bytes from our communcation buffer "m_bytes"
304 packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length)));
305 m_bytes.erase (0, length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000306
307 if (log)
308 {
309 PacketStreamType log_strm;
Greg Clayton0fa51242011-07-19 03:57:15 +0000310 DumpPacket (log_strm, packet);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000311
Greg Clayton0fa51242011-07-19 03:57:15 +0000312 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton8d2ea282011-07-17 20:36:25 +0000313 }
Greg Claytond52d00f2011-07-16 03:19:08 +0000314 return true;
315 }
316 }
317 break;
318
319 default:
320 // Unrecognized reply command byte, erase this byte and try to get back on track
321 if (log)
322 log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
323 __FUNCTION__,
324 (uint8_t)m_bytes[0]);
325 m_bytes.erase(0, 1);
326 break;
327 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000328 }
329 packet.Clear();
330 return false;
331}
332
Greg Clayton1e5b0212011-07-15 16:31:38 +0000333
Greg Claytond52d00f2011-07-16 03:19:08 +0000334bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000335CommunicationKDP::SendRequestConnect (uint16_t reply_port,
336 uint16_t exc_port,
337 const char *greeting)
Greg Clayton1e5b0212011-07-15 16:31:38 +0000338{
Greg Clayton0fa51242011-07-19 03:57:15 +0000339 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000340 if (greeting == NULL)
341 greeting = "";
342
Greg Clayton7b139222011-07-21 01:12:01 +0000343 const CommandType command = KDP_CONNECT;
Greg Clayton8d2ea282011-07-17 20:36:25 +0000344 // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL
345 const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
Greg Claytond52d00f2011-07-16 03:19:08 +0000346 const uint32_t request_sequence_id = m_request_sequence_id;
347 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000348 // Always send connect ports as little endian
349 request_packet.SetByteOrder (eByteOrderLittle);
350 request_packet.PutHex16 (reply_port);
351 request_packet.PutHex16 (exc_port);
352 request_packet.SetByteOrder (m_byte_order);
353 request_packet.PutCString (greeting);
Greg Claytond52d00f2011-07-16 03:19:08 +0000354 DataExtractor reply_packet;
355 return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
Greg Clayton1e5b0212011-07-15 16:31:38 +0000356}
357
Greg Claytond52d00f2011-07-16 03:19:08 +0000358void
359CommunicationKDP::ClearKDPSettings ()
360{
361 m_request_sequence_id = 0;
362 m_kdp_version_version = 0;
363 m_kdp_version_feature = 0;
364 m_kdp_hostinfo_cpu_mask = 0;
365 m_kdp_hostinfo_cpu_type = 0;
366 m_kdp_hostinfo_cpu_subtype = 0;
367}
368
369bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000370CommunicationKDP::SendRequestReattach (uint16_t reply_port)
Greg Claytond52d00f2011-07-16 03:19:08 +0000371{
Greg Clayton0fa51242011-07-19 03:57:15 +0000372 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000373 const CommandType command = KDP_REATTACH;
Greg Claytond52d00f2011-07-16 03:19:08 +0000374 // Length is 8 bytes for the header plus 2 bytes for the reply UDP port
375 const uint32_t command_length = 8 + 2;
376 const uint32_t request_sequence_id = m_request_sequence_id;
377 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000378 // Always send connect ports as little endian
379 request_packet.SetByteOrder (eByteOrderLittle);
Greg Claytond52d00f2011-07-16 03:19:08 +0000380 request_packet.PutHex16(reply_port);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000381 request_packet.SetByteOrder (m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000382 DataExtractor reply_packet;
383 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
384 {
385 // Reset the sequence ID to zero for reattach
386 ClearKDPSettings ();
387 uint32_t offset = 4;
388 m_session_key = reply_packet.GetU32 (&offset);
389 return true;
390 }
391 return false;
392}
393
394uint32_t
395CommunicationKDP::GetVersion ()
396{
397 if (!VersionIsValid())
398 SendRequestVersion();
399 return m_kdp_version_version;
400}
401
402uint32_t
403CommunicationKDP::GetFeatureFlags ()
404{
405 if (!VersionIsValid())
406 SendRequestVersion();
407 return m_kdp_version_feature;
408}
409
410bool
411CommunicationKDP::SendRequestVersion ()
412{
Greg Clayton0fa51242011-07-19 03:57:15 +0000413 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000414 const CommandType command = KDP_VERSION;
Greg Claytond52d00f2011-07-16 03:19:08 +0000415 const uint32_t command_length = 8;
416 const uint32_t request_sequence_id = m_request_sequence_id;
417 MakeRequestPacketHeader (command, request_packet, command_length);
418 DataExtractor reply_packet;
419 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
420 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000421 uint32_t offset = 8;
422 m_kdp_version_version = reply_packet.GetU32 (&offset);
423 m_kdp_version_feature = reply_packet.GetU32 (&offset);
424 return true;
425 }
426 return false;
427}
428
Greg Clayton7b139222011-07-21 01:12:01 +0000429#if 0 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...
430const char *
431CommunicationKDP::GetImagePath ()
432{
433 if (m_image_path.empty())
434 SendRequestImagePath();
435 return m_image_path.c_str();
436}
437
438bool
439CommunicationKDP::SendRequestImagePath ()
440{
441 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
442 const CommandType command = KDP_IMAGEPATH;
443 const uint32_t command_length = 8;
444 const uint32_t request_sequence_id = m_request_sequence_id;
445 MakeRequestPacketHeader (command, request_packet, command_length);
446 DataExtractor reply_packet;
447 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
448 {
449 const char *path = reply_packet.PeekCStr(8);
450 if (path && path[0])
451 m_kernel_version.assign (path);
452 return true;
453 }
454 return false;
455}
456#endif
457
Greg Claytond52d00f2011-07-16 03:19:08 +0000458uint32_t
459CommunicationKDP::GetCPUMask ()
460{
461 if (!HostInfoIsValid())
462 SendRequestHostInfo();
463 return m_kdp_hostinfo_cpu_mask;
464}
465
466uint32_t
467CommunicationKDP::GetCPUType ()
468{
469 if (!HostInfoIsValid())
470 SendRequestHostInfo();
471 return m_kdp_hostinfo_cpu_type;
472}
473
474uint32_t
475CommunicationKDP::GetCPUSubtype ()
476{
477 if (!HostInfoIsValid())
478 SendRequestHostInfo();
479 return m_kdp_hostinfo_cpu_subtype;
480}
481
482bool
483CommunicationKDP::SendRequestHostInfo ()
484{
Greg Clayton0fa51242011-07-19 03:57:15 +0000485 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000486 const CommandType command = KDP_HOSTINFO;
Greg Claytond52d00f2011-07-16 03:19:08 +0000487 const uint32_t command_length = 8;
488 const uint32_t request_sequence_id = m_request_sequence_id;
489 MakeRequestPacketHeader (command, request_packet, command_length);
490 DataExtractor reply_packet;
491 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
492 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000493 uint32_t offset = 8;
Greg Clayton0fa51242011-07-19 03:57:15 +0000494 m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
495 m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
496 m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
497
498 ArchSpec kernel_arch;
499 kernel_arch.SetArchitecture (eArchTypeMachO,
500 m_kdp_hostinfo_cpu_type,
501 m_kdp_hostinfo_cpu_subtype);
502
503 m_addr_byte_size = kernel_arch.GetAddressByteSize();
504 m_byte_order = kernel_arch.GetByteOrder();
Greg Claytond52d00f2011-07-16 03:19:08 +0000505 return true;
506 }
507 return false;
508}
509
Greg Clayton234981a2011-07-20 03:41:06 +0000510const char *
511CommunicationKDP::GetKernelVersion ()
512{
513 if (m_kernel_version.empty())
514 SendRequestKernelVersion ();
515 return m_kernel_version.c_str();
516}
517
518bool
519CommunicationKDP::SendRequestKernelVersion ()
520{
521 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000522 const CommandType command = KDP_KERNELVERSION;
Greg Clayton234981a2011-07-20 03:41:06 +0000523 const uint32_t command_length = 8;
524 const uint32_t request_sequence_id = m_request_sequence_id;
525 MakeRequestPacketHeader (command, request_packet, command_length);
526 DataExtractor reply_packet;
527 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
528 {
529 const char *kernel_version_cstr = reply_packet.PeekCStr(8);
530 if (kernel_version_cstr && kernel_version_cstr[0])
531 m_kernel_version.assign (kernel_version_cstr);
532 return true;
533 }
534 return false;
535}
536
Greg Claytond52d00f2011-07-16 03:19:08 +0000537bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000538CommunicationKDP::SendRequestDisconnect ()
Greg Clayton1e5b0212011-07-15 16:31:38 +0000539{
Greg Clayton0fa51242011-07-19 03:57:15 +0000540 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000541 const CommandType command = KDP_DISCONNECT;
Greg Claytond52d00f2011-07-16 03:19:08 +0000542 const uint32_t command_length = 8;
543 const uint32_t request_sequence_id = m_request_sequence_id;
544 MakeRequestPacketHeader (command, request_packet, command_length);
545 DataExtractor reply_packet;
546 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
547 {
548 // Are we supposed to get a reply for disconnect?
549 }
550 ClearKDPSettings ();
551 return true;
Greg Clayton1e5b0212011-07-15 16:31:38 +0000552}
553
Greg Clayton0fa51242011-07-19 03:57:15 +0000554uint32_t
555CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr,
556 void *dst,
557 uint32_t dst_len,
558 Error &error)
559{
560 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
561 bool use_64 = (GetVersion() >= 11);
562 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +0000563 const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM;
Greg Clayton0fa51242011-07-19 03:57:15 +0000564 // Size is header + address size + uint32_t length
565 const uint32_t command_length = 8 + command_addr_byte_size + 4;
566 const uint32_t request_sequence_id = m_request_sequence_id;
567 MakeRequestPacketHeader (command, request_packet, command_length);
568 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
569 request_packet.PutHex32 (dst_len);
570 DataExtractor reply_packet;
571 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
572 {
Greg Clayton0fa51242011-07-19 03:57:15 +0000573 uint32_t offset = 8;
574 uint32_t kdp_error = reply_packet.GetU32 (&offset);
575 uint32_t src_len = reply_packet.GetByteSize() - 12;
576
577 if (src_len > 0)
578 {
579 const void *src = reply_packet.GetData(&offset, src_len);
580 if (src)
581 {
582 ::memcpy (dst, src, src_len);
583 error.Clear();
584 return src_len;
585 }
586 }
587 if (kdp_error)
588 error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error);
589 else
590 error.SetErrorString ("kdp read memory failed");
591 }
592 return 0;
593}
594
Greg Claytonec15f502011-07-20 01:32:50 +0000595
596uint32_t
597CommunicationKDP::SendRequestWriteMemory (lldb::addr_t addr,
598 const void *src,
599 uint32_t src_len,
600 Error &error)
601{
602 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
603 bool use_64 = (GetVersion() >= 11);
604 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +0000605 const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM;
Greg Claytonec15f502011-07-20 01:32:50 +0000606 // Size is header + address size + uint32_t length
607 const uint32_t command_length = 8 + command_addr_byte_size + 4;
608 const uint32_t request_sequence_id = m_request_sequence_id;
609 MakeRequestPacketHeader (command, request_packet, command_length);
610 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
611 request_packet.PutHex32 (src_len);
612 request_packet.PutBytesAsRawHex8(src, src_len);
613
614 DataExtractor reply_packet;
615 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
616 {
617 uint32_t offset = 8;
618 uint32_t kdp_error = reply_packet.GetU32 (&offset);
619 if (kdp_error)
620 error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error);
621 else
622 {
623 error.Clear();
624 return src_len;
625 }
626 }
627 return 0;
628}
629
Greg Clayton0fa51242011-07-19 03:57:15 +0000630const char *
631CommunicationKDP::GetCommandAsCString (uint8_t command)
632{
633 switch (command)
634 {
Greg Clayton7b139222011-07-21 01:12:01 +0000635 case KDP_CONNECT: return "KDP_CONNECT";
636 case KDP_DISCONNECT: return "KDP_DISCONNECT";
637 case KDP_HOSTINFO: return "KDP_HOSTINFO";
638 case KDP_VERSION: return "KDP_VERSION";
639 case KDP_MAXBYTES: return "KDP_MAXBYTES";
640 case KDP_READMEM: return "KDP_READMEM";
641 case KDP_WRITEMEM: return "KDP_WRITEMEM";
642 case KDP_READREGS: return "KDP_READREGS";
643 case KDP_WRITEREGS: return "KDP_WRITEREGS";
644 case KDP_LOAD: return "KDP_LOAD";
645 case KDP_IMAGEPATH: return "KDP_IMAGEPATH";
646 case KDP_SUSPEND: return "KDP_SUSPEND";
647 case KDP_RESUMECPUS: return "KDP_RESUMECPUS";
648 case KDP_EXCEPTION: return "KDP_EXCEPTION";
649 case KDP_TERMINATION: return "KDP_TERMINATION";
650 case KDP_BREAKPOINT_SET: return "KDP_BREAKPOINT_SET";
651 case KDP_BREAKPOINT_REMOVE: return "KDP_BREAKPOINT_REMOVE";
652 case KDP_REGIONS: return "KDP_REGIONS";
653 case KDP_REATTACH: return "KDP_REATTACH";
654 case KDP_HOSTREBOOT: return "KDP_HOSTREBOOT";
655 case KDP_READMEM64: return "KDP_READMEM64";
656 case KDP_WRITEMEM64: return "KDP_WRITEMEM64";
657 case KDP_BREAKPOINT_SET64: return "KDP_BREAKPOINT64_SET";
658 case KDP_BREAKPOINT_REMOVE64: return "KDP_BREAKPOINT64_REMOVE";
659 case KDP_KERNELVERSION: return "KDP_KERNELVERSION";
Greg Clayton0fa51242011-07-19 03:57:15 +0000660 }
661 return NULL;
662}
663
664void
665CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len)
666{
667 DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size);
668 DumpPacket (s, extractor);
669}
670
671void
672CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
673{
674 const char *error_desc = NULL;
675 if (packet.GetByteSize() < 8)
676 {
677 error_desc = "error: invalid packet (too short): ";
678 }
679 else
680 {
681 uint32_t offset = 0;
682 const uint8_t first_packet_byte = packet.GetU8 (&offset);
683 const uint8_t sequence_id = packet.GetU8 (&offset);
684 const uint16_t length = packet.GetU16 (&offset);
685 const uint32_t key = packet.GetU32 (&offset);
686 const CommandType command = ExtractCommand (first_packet_byte);
687 const char *command_name = GetCommandAsCString (command);
688 if (command_name)
689 {
690 const bool is_reply = ExtractIsReply(first_packet_byte);
691 s.Printf ("%s {%u:%u} <0x%4.4x> %s",
692 is_reply ? "<--" : "-->",
693 key,
694 sequence_id,
695 length,
696 command_name);
697
698 if (is_reply)
699 {
700 // Dump request reply packets
701 switch (command)
702 {
Greg Claytonec15f502011-07-20 01:32:50 +0000703 // Commands that return a single 32 bit error
Greg Clayton7b139222011-07-21 01:12:01 +0000704 case KDP_CONNECT:
705 case KDP_WRITEMEM:
706 case KDP_WRITEMEM64:
707 case KDP_BREAKPOINT_SET:
708 case KDP_BREAKPOINT_REMOVE:
709 case KDP_BREAKPOINT_SET64:
710 case KDP_BREAKPOINT_REMOVE64:
711 case KDP_WRITEREGS:
712 case KDP_LOAD:
Greg Clayton0fa51242011-07-19 03:57:15 +0000713 {
714 const uint32_t error = packet.GetU32 (&offset);
715 s.Printf(" (error=0x%8.8x)", error);
716 }
717 break;
718
Greg Clayton7b139222011-07-21 01:12:01 +0000719 case KDP_DISCONNECT:
720 case KDP_REATTACH:
721 case KDP_HOSTREBOOT:
722 case KDP_SUSPEND:
723 case KDP_RESUMECPUS:
724 case KDP_EXCEPTION:
725 case KDP_TERMINATION:
Greg Clayton0fa51242011-07-19 03:57:15 +0000726 // No return value for the reply, just the header to ack
Greg Claytonec15f502011-07-20 01:32:50 +0000727 s.PutCString(" ()");
Greg Clayton0fa51242011-07-19 03:57:15 +0000728 break;
729
Greg Clayton7b139222011-07-21 01:12:01 +0000730 case KDP_HOSTINFO:
Greg Clayton0fa51242011-07-19 03:57:15 +0000731 {
732 const uint32_t cpu_mask = packet.GetU32 (&offset);
733 const uint32_t cpu_type = packet.GetU32 (&offset);
734 const uint32_t cpu_subtype = packet.GetU32 (&offset);
735 s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype);
736 }
737 break;
738
Greg Clayton7b139222011-07-21 01:12:01 +0000739 case KDP_VERSION:
Greg Clayton0fa51242011-07-19 03:57:15 +0000740 {
741 const uint32_t version = packet.GetU32 (&offset);
742 const uint32_t feature = packet.GetU32 (&offset);
743 s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
744 }
745 break;
746
Greg Clayton7b139222011-07-21 01:12:01 +0000747 case KDP_REGIONS:
Greg Clayton0fa51242011-07-19 03:57:15 +0000748 {
749 const uint32_t region_count = packet.GetU32 (&offset);
750 s.Printf(" (count = %u", region_count);
751 for (uint32_t i=0; i<region_count; ++i)
752 {
753 const addr_t region_addr = packet.GetPointer (&offset);
754 const uint32_t region_size = packet.GetU32 (&offset);
755 const uint32_t region_prot = packet.GetU32 (&offset);
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000756 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));
Greg Clayton0fa51242011-07-19 03:57:15 +0000757 }
758 }
759 break;
760
Greg Clayton7b139222011-07-21 01:12:01 +0000761 case KDP_READMEM:
762 case KDP_READMEM64:
Greg Clayton0fa51242011-07-19 03:57:15 +0000763 {
764 const uint32_t error = packet.GetU32 (&offset);
Greg Claytonec15f502011-07-20 01:32:50 +0000765 const uint32_t count = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000766 s.Printf(" (error = 0x%8.8x:\n", error);
Greg Clayton0fa51242011-07-19 03:57:15 +0000767 if (count > 0)
Greg Clayton234981a2011-07-20 03:41:06 +0000768 packet.Dump (&s, // Stream to dump to
769 offset, // Offset within "packet"
770 eFormatBytesWithASCII, // Format to use
771 1, // Size of each item in bytes
772 count, // Number of items
773 16, // Number per line
774 m_last_read_memory_addr, // Don't show addresses before each line
775 0, 0); // No bitfields
Greg Clayton0fa51242011-07-19 03:57:15 +0000776 }
777 break;
778
Greg Clayton7b139222011-07-21 01:12:01 +0000779 case KDP_READREGS:
Greg Claytonec15f502011-07-20 01:32:50 +0000780 {
781 const uint32_t error = packet.GetU32 (&offset);
782 const uint32_t count = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000783 s.Printf(" (error = 0x%8.8x regs:\n", error);
Greg Claytonec15f502011-07-20 01:32:50 +0000784 if (count > 0)
785 packet.Dump (&s, // Stream to dump to
786 offset, // Offset within "packet"
787 eFormatHex, // Format to use
788 m_addr_byte_size, // Size of each item in bytes
789 count / m_addr_byte_size, // Number of items
790 16 / m_addr_byte_size, // Number per line
791 LLDB_INVALID_ADDRESS, // Don't show addresses before each line
792 0, 0); // No bitfields
793 }
794 break;
795
Greg Clayton7b139222011-07-21 01:12:01 +0000796 case KDP_KERNELVERSION:
Greg Clayton234981a2011-07-20 03:41:06 +0000797 {
798 const char *kernel_version = packet.PeekCStr(8);
799 s.Printf(" (version = \"%s\")", kernel_version);
800 }
801 break;
802
Greg Clayton7b139222011-07-21 01:12:01 +0000803 case KDP_MAXBYTES:
Greg Clayton234981a2011-07-20 03:41:06 +0000804 {
805 const uint32_t max_bytes = packet.GetU32 (&offset);
806 s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes);
807 }
808 break;
Greg Clayton7b139222011-07-21 01:12:01 +0000809 case KDP_IMAGEPATH:
Greg Clayton234981a2011-07-20 03:41:06 +0000810 {
811 const char *path = packet.GetCStr(&offset);
812 s.Printf(" (path = \"%s\")", path);
813 }
814 break;
815 default:
Greg Claytonec15f502011-07-20 01:32:50 +0000816 s.Printf(" (add support for dumping this packet reply!!!");
Greg Clayton0fa51242011-07-19 03:57:15 +0000817 break;
818
819 }
820 }
821 else
822 {
823 // Dump request packets
824 switch (command)
825 {
Greg Clayton7b139222011-07-21 01:12:01 +0000826 case KDP_CONNECT:
Greg Clayton0fa51242011-07-19 03:57:15 +0000827 {
828 const uint16_t reply_port = packet.GetU16 (&offset);
829 const uint16_t exc_port = packet.GetU16 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000830 s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset));
Greg Clayton0fa51242011-07-19 03:57:15 +0000831 }
832 break;
833
Greg Clayton7b139222011-07-21 01:12:01 +0000834 case KDP_DISCONNECT:
835 case KDP_HOSTREBOOT:
836 case KDP_HOSTINFO:
837 case KDP_VERSION:
838 case KDP_REGIONS:
839 case KDP_KERNELVERSION:
840 case KDP_MAXBYTES:
841 case KDP_IMAGEPATH:
842 case KDP_SUSPEND:
Greg Clayton0fa51242011-07-19 03:57:15 +0000843 // No args, just the header in the request...
Greg Clayton234981a2011-07-20 03:41:06 +0000844 s.PutCString(" ()");
845 break;
846
Greg Clayton7b139222011-07-21 01:12:01 +0000847 case KDP_RESUMECPUS:
Greg Clayton234981a2011-07-20 03:41:06 +0000848 {
849 const uint32_t cpu_mask = packet.GetU32 (&offset);
850 s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask);
851 }
Greg Clayton0fa51242011-07-19 03:57:15 +0000852 break;
853
Greg Clayton7b139222011-07-21 01:12:01 +0000854 case KDP_READMEM:
Greg Clayton0fa51242011-07-19 03:57:15 +0000855 {
856 const uint32_t addr = packet.GetU32 (&offset);
857 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000858 s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size);
Greg Clayton234981a2011-07-20 03:41:06 +0000859 m_last_read_memory_addr = addr;
Greg Clayton0fa51242011-07-19 03:57:15 +0000860 }
861 break;
862
Greg Clayton7b139222011-07-21 01:12:01 +0000863 case KDP_WRITEMEM:
Greg Claytonec15f502011-07-20 01:32:50 +0000864 {
865 const uint32_t addr = packet.GetU32 (&offset);
866 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000867 s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size);
Greg Claytonec15f502011-07-20 01:32:50 +0000868 if (size > 0)
869 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
870 }
871 break;
872
Greg Clayton7b139222011-07-21 01:12:01 +0000873 case KDP_READMEM64:
Greg Clayton0fa51242011-07-19 03:57:15 +0000874 {
875 const uint64_t addr = packet.GetU64 (&offset);
876 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000877 s.Printf(" (addr = 0x%16.16llx, size = %u)", addr, size);
Greg Clayton234981a2011-07-20 03:41:06 +0000878 m_last_read_memory_addr = addr;
Greg Clayton0fa51242011-07-19 03:57:15 +0000879 }
880 break;
881
Greg Clayton7b139222011-07-21 01:12:01 +0000882 case KDP_WRITEMEM64:
Greg Claytonec15f502011-07-20 01:32:50 +0000883 {
884 const uint64_t addr = packet.GetU64 (&offset);
885 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000886 s.Printf(" (addr = 0x%16.16llx, size = %u, bytes = \n", addr, size);
Greg Claytonec15f502011-07-20 01:32:50 +0000887 if (size > 0)
888 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
889 }
890 break;
891
Greg Clayton7b139222011-07-21 01:12:01 +0000892 case KDP_READREGS:
Greg Clayton0fa51242011-07-19 03:57:15 +0000893 {
894 const uint32_t cpu = packet.GetU32 (&offset);
895 const uint32_t flavor = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000896 s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor);
Greg Clayton0fa51242011-07-19 03:57:15 +0000897 }
898 break;
899
Greg Clayton7b139222011-07-21 01:12:01 +0000900 case KDP_WRITEREGS:
Greg Claytonec15f502011-07-20 01:32:50 +0000901 {
902 const uint32_t cpu = packet.GetU32 (&offset);
903 const uint32_t flavor = packet.GetU32 (&offset);
904 const uint32_t nbytes = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000905 s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor);
Greg Claytonec15f502011-07-20 01:32:50 +0000906 if (nbytes > 0)
907 packet.Dump (&s, // Stream to dump to
908 offset, // Offset within "packet"
909 eFormatHex, // Format to use
910 m_addr_byte_size, // Size of each item in bytes
911 nbytes / m_addr_byte_size, // Number of items
912 16 / m_addr_byte_size, // Number per line
913 LLDB_INVALID_ADDRESS, // Don't show addresses before each line
914 0, 0); // No bitfields
915 }
916 break;
917
Greg Claytonec15f502011-07-20 01:32:50 +0000918
Greg Clayton7b139222011-07-21 01:12:01 +0000919 case KDP_BREAKPOINT_SET:
920 case KDP_BREAKPOINT_REMOVE:
Greg Clayton234981a2011-07-20 03:41:06 +0000921 {
922 const uint32_t addr = packet.GetU32 (&offset);
923 s.Printf(" (addr = 0x%8.8x)", addr);
924 }
925 break;
926
Greg Clayton7b139222011-07-21 01:12:01 +0000927 case KDP_BREAKPOINT_SET64:
928 case KDP_BREAKPOINT_REMOVE64:
Greg Clayton234981a2011-07-20 03:41:06 +0000929 {
930 const uint64_t addr = packet.GetU64 (&offset);
931 s.Printf(" (addr = 0x%16.16llx)", addr);
932 }
933 break;
934
935
Greg Clayton7b139222011-07-21 01:12:01 +0000936 case KDP_LOAD:
Greg Clayton234981a2011-07-20 03:41:06 +0000937 {
938 const char *path = packet.GetCStr(&offset);
939 s.Printf(" (path = \"%s\")", path);
940 }
941 break;
942
Greg Clayton7b139222011-07-21 01:12:01 +0000943 case KDP_EXCEPTION:
Greg Clayton234981a2011-07-20 03:41:06 +0000944 {
945 const uint32_t count = packet.GetU32 (&offset);
946
947 s.Printf(" (count = %u:", count);
948 for (uint32_t i=0; i<count; ++i)
949 {
950 const uint32_t cpu = packet.GetU32 (&offset);
951 const uint32_t exc = packet.GetU32 (&offset);
952 const uint32_t code = packet.GetU32 (&offset);
953 const uint32_t subcode = packet.GetU32 (&offset);
954 const char *exc_cstr = NULL;
955 switch (exc)
956 {
957 case 1: exc_cstr = "EXC_BAD_ACCESS"; break;
958 case 2: exc_cstr = "EXC_BAD_INSTRUCTION"; break;
959 case 3: exc_cstr = "EXC_ARITHMETIC"; break;
960 case 4: exc_cstr = "EXC_EMULATION"; break;
961 case 5: exc_cstr = "EXC_SOFTWARE"; break;
962 case 6: exc_cstr = "EXC_BREAKPOINT"; break;
963 case 7: exc_cstr = "EXC_SYSCALL"; break;
964 case 8: exc_cstr = "EXC_MACH_SYSCALL"; break;
965 case 9: exc_cstr = "EXC_RPC_ALERT"; break;
966 case 10: exc_cstr = "EXC_CRASH"; break;
967 default:
968 break;
969 }
970
971 s.Printf ("\n cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)\n",
972 cpu, exc_cstr, exc, code, code, subcode, subcode);
973 }
974 }
975 break;
976
Greg Clayton7b139222011-07-21 01:12:01 +0000977 case KDP_TERMINATION:
Greg Clayton234981a2011-07-20 03:41:06 +0000978 {
979 const uint32_t term_code = packet.GetU32 (&offset);
980 const uint32_t exit_code = packet.GetU32 (&offset);
981 s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code);
982 }
Greg Clayton0fa51242011-07-19 03:57:15 +0000983 break;
984
Greg Clayton7b139222011-07-21 01:12:01 +0000985 case KDP_REATTACH:
Greg Clayton0fa51242011-07-19 03:57:15 +0000986 {
987 const uint16_t reply_port = packet.GetU16 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000988 s.Printf(" (reply_port = %u)", reply_port);
Greg Clayton0fa51242011-07-19 03:57:15 +0000989 }
990 break;
Greg Clayton0fa51242011-07-19 03:57:15 +0000991 }
992 }
993 }
994 else
995 {
996 error_desc = "error: invalid packet command: ";
997 }
998 }
999
1000 if (error_desc)
1001 {
1002 s.PutCString (error_desc);
1003
1004 packet.Dump (&s, // Stream to dump to
1005 0, // Offset into "packet"
1006 eFormatBytes, // Dump as hex bytes
1007 1, // Size of each item is 1 for single bytes
1008 packet.GetByteSize(), // Number of bytes
1009 UINT32_MAX, // Num bytes per line
1010 LLDB_INVALID_ADDRESS, // Base address
1011 0, 0); // Bitfield info set to not do anything bitfield related
1012 }
1013}
1014
1015uint32_t
1016CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
1017 uint32_t flavor,
Greg Claytonea636012012-09-21 01:55:30 +00001018 void *dst,
Greg Clayton0fa51242011-07-19 03:57:15 +00001019 uint32_t dst_len,
1020 Error &error)
1021{
1022 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001023 const CommandType command = KDP_READREGS;
Greg Clayton0fa51242011-07-19 03:57:15 +00001024 // Size is header + 4 byte cpu and 4 byte flavor
1025 const uint32_t command_length = 8 + 4 + 4;
1026 const uint32_t request_sequence_id = m_request_sequence_id;
1027 MakeRequestPacketHeader (command, request_packet, command_length);
1028 request_packet.PutHex32 (cpu);
1029 request_packet.PutHex32 (flavor);
1030 DataExtractor reply_packet;
1031 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1032 {
Greg Clayton0fa51242011-07-19 03:57:15 +00001033 uint32_t offset = 8;
1034 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1035 uint32_t src_len = reply_packet.GetByteSize() - 12;
1036
1037 if (src_len > 0)
1038 {
1039 const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
1040 const void *src = reply_packet.GetData(&offset, bytes_to_copy);
1041 if (src)
1042 {
1043 ::memcpy (dst, src, bytes_to_copy);
1044 error.Clear();
1045 // Return the number of bytes we could have returned regardless if
1046 // we copied them or not, just so we know when things don't match up
Greg Claytonea636012012-09-21 01:55:30 +00001047 return src_len;
Greg Clayton0fa51242011-07-19 03:57:15 +00001048 }
1049 }
1050 if (kdp_error)
1051 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
1052 else
1053 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
1054 }
1055 return 0;
1056}
1057
Greg Claytonea636012012-09-21 01:55:30 +00001058uint32_t
1059CommunicationKDP::SendRequestWriteRegisters (uint32_t cpu,
1060 uint32_t flavor,
1061 const void *src,
1062 uint32_t src_len,
1063 Error &error)
1064{
1065 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1066 const CommandType command = KDP_WRITEREGS;
1067 // Size is header + 4 byte cpu and 4 byte flavor
1068 const uint32_t command_length = 8 + 4 + 4;
1069 const uint32_t request_sequence_id = m_request_sequence_id;
1070 MakeRequestPacketHeader (command, request_packet, command_length);
1071 request_packet.PutHex32 (cpu);
1072 request_packet.PutHex32 (flavor);
1073 request_packet.Write(src, src_len);
1074 DataExtractor reply_packet;
1075 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1076 {
1077 uint32_t offset = 8;
1078 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1079 if (kdp_error == 0)
1080 return src_len;
1081 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
1082 }
1083 return 0;
1084}
1085
Greg Clayton234981a2011-07-20 03:41:06 +00001086
1087bool
1088CommunicationKDP::SendRequestResume (uint32_t cpu_mask)
1089{
1090 if (cpu_mask == 0)
1091 cpu_mask = GetCPUMask();
1092 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001093 const CommandType command = KDP_RESUMECPUS;
Greg Clayton234981a2011-07-20 03:41:06 +00001094 const uint32_t command_length = 12;
1095 const uint32_t request_sequence_id = m_request_sequence_id;
1096 MakeRequestPacketHeader (command, request_packet, command_length);
1097 request_packet.PutHex32(cpu_mask);
1098
1099 DataExtractor reply_packet;
1100 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1101 return true;
1102 return false;
1103}
1104
1105bool
1106CommunicationKDP::SendRequestBreakpoint (bool set, addr_t addr)
1107{
1108 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1109 bool use_64 = (GetVersion() >= 11);
1110 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +00001111 const CommandType command = set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET ):
1112 (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE);
Greg Clayton234981a2011-07-20 03:41:06 +00001113
1114 const uint32_t command_length = 8 + command_addr_byte_size;
1115 const uint32_t request_sequence_id = m_request_sequence_id;
1116 MakeRequestPacketHeader (command, request_packet, command_length);
1117 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
1118
1119 DataExtractor reply_packet;
1120 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
Greg Clayton1bc04ed2011-07-29 22:26:36 +00001121 {
1122 uint32_t offset = 8;
1123 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1124 if (kdp_error == 0)
1125 return true;
1126 }
Greg Clayton234981a2011-07-20 03:41:06 +00001127 return false;
1128}
1129
1130bool
1131CommunicationKDP::SendRequestSuspend ()
1132{
1133 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001134 const CommandType command = KDP_SUSPEND;
Greg Clayton234981a2011-07-20 03:41:06 +00001135 const uint32_t command_length = 8;
1136 const uint32_t request_sequence_id = m_request_sequence_id;
1137 MakeRequestPacketHeader (command, request_packet, command_length);
1138 DataExtractor reply_packet;
1139 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1140 return true;
1141 return false;
1142}
1143