blob: c0e62888cf8e8691583294c4e886439d6f3b0b0d [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 Clayton3acaa922012-09-25 02:40:06 +000045 m_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{
Greg Clayton3acaa922012-09-25 02:40:06 +0000102 if (IsRunning())
103 {
104 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
105 if (log)
106 {
107 PacketStreamType log_strm;
108 DumpPacket (log_strm, request_packet.GetData(), request_packet.GetSize());
109 log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
110 }
111 return false;
112 }
Greg Claytond52d00f2011-07-16 03:19:08 +0000113
Greg Clayton3acaa922012-09-25 02:40:06 +0000114 Mutex::Locker locker(m_sequence_mutex);
115#ifdef LLDB_CONFIGURATION_DEBUG
116 // NOTE: this only works for packets that are in native endian byte order
117 assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2)));
118#endif
Greg Claytond52d00f2011-07-16 03:19:08 +0000119 if (SendRequestPacketNoLock(request_packet))
120 {
Greg Clayton8d2ea282011-07-17 20:36:25 +0000121 if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
Greg Claytond52d00f2011-07-16 03:19:08 +0000122 {
123 uint32_t offset = 0;
124 const uint8_t reply_command = reply_packet.GetU8 (&offset);
125 const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
126 if ((reply_command & eCommandTypeMask) == command)
127 {
128 if (request_sequence_id == reply_sequence_id)
Greg Clayton3acaa922012-09-25 02:40:06 +0000129 {
130 if (command == KDP_RESUMECPUS)
131 m_is_running.SetValue(true, eBroadcastAlways);
Greg Claytond52d00f2011-07-16 03:19:08 +0000132 return true;
Greg Clayton3acaa922012-09-25 02:40:06 +0000133 }
Greg Claytond52d00f2011-07-16 03:19:08 +0000134 }
135 }
136 }
137 reply_packet.Clear();
138 return false;
139}
Greg Clayton363be3f2011-07-15 03:27:12 +0000140
Greg Clayton1e5b0212011-07-15 16:31:38 +0000141bool
Greg Claytond52d00f2011-07-16 03:19:08 +0000142CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +0000143{
144 if (IsConnected())
145 {
Greg Clayton1e5b0212011-07-15 16:31:38 +0000146 const char *packet_data = request_packet.GetData();
147 const size_t packet_size = request_packet.GetSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000148
149 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
150 if (log)
Greg Clayton1e5b0212011-07-15 16:31:38 +0000151 {
Greg Clayton0fa51242011-07-19 03:57:15 +0000152 PacketStreamType log_strm;
153 DumpPacket (log_strm, packet_data, packet_size);
154 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton1e5b0212011-07-15 16:31:38 +0000155 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000156 ConnectionStatus status = eConnectionStatusSuccess;
Greg Clayton363be3f2011-07-15 03:27:12 +0000157
Greg Clayton1e5b0212011-07-15 16:31:38 +0000158 size_t bytes_written = Write (packet_data,
159 packet_size,
160 status,
161 NULL);
162
163 if (bytes_written == packet_size)
164 return true;
165
166 if (log)
Greg Clayton851e30e2012-09-18 18:04:04 +0000167 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 +0000168 }
169 return false;
Greg Clayton363be3f2011-07-15 03:27:12 +0000170}
171
172bool
Greg Clayton516f0842012-04-11 00:24:49 +0000173CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker)
Greg Clayton363be3f2011-07-15 03:27:12 +0000174{
Jim Ingham1b584eb2012-05-04 23:02:50 +0000175 return locker.TryLock (m_sequence_mutex);
Greg Clayton363be3f2011-07-15 03:27:12 +0000176}
177
178
179bool
180CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
181{
Greg Clayton3acaa922012-09-25 02:40:06 +0000182 return m_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
Greg Clayton363be3f2011-07-15 03:27:12 +0000183}
184
185size_t
Greg Claytond52d00f2011-07-16 03:19:08 +0000186CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &packet, uint32_t timeout_usec)
Greg Clayton363be3f2011-07-15 03:27:12 +0000187{
188 Mutex::Locker locker(m_sequence_mutex);
189 return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
190}
191
192size_t
Greg Claytond52d00f2011-07-16 03:19:08 +0000193CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec)
Greg Clayton363be3f2011-07-15 03:27:12 +0000194{
195 uint8_t buffer[8192];
196 Error error;
197
198 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
199
200 // Check for a packet from our cache first without trying any reading...
201 if (CheckForPacket (NULL, 0, packet))
Greg Claytond52d00f2011-07-16 03:19:08 +0000202 return packet.GetByteSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000203
204 bool timed_out = false;
205 while (IsConnected() && !timed_out)
206 {
Johnny Chen1e3a5222011-07-21 19:00:59 +0000207 lldb::ConnectionStatus status = eConnectionStatusNoConnection;
Greg Clayton363be3f2011-07-15 03:27:12 +0000208 size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
209
210 if (log)
Greg Clayton851e30e2012-09-18 18:04:04 +0000211 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 +0000212 __PRETTY_FUNCTION__,
213 timeout_usec,
214 Communication::ConnectionStatusAsCString (status),
215 error.AsCString(),
Greg Clayton851e30e2012-09-18 18:04:04 +0000216 (uint64_t)bytes_read);
Greg Clayton363be3f2011-07-15 03:27:12 +0000217
218 if (bytes_read > 0)
219 {
220 if (CheckForPacket (buffer, bytes_read, packet))
Greg Claytond52d00f2011-07-16 03:19:08 +0000221 return packet.GetByteSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000222 }
223 else
224 {
225 switch (status)
226 {
227 case eConnectionStatusTimedOut:
228 timed_out = true;
229 break;
230 case eConnectionStatusSuccess:
231 //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
232 break;
233
234 case eConnectionStatusEndOfFile:
235 case eConnectionStatusNoConnection:
236 case eConnectionStatusLostConnection:
237 case eConnectionStatusError:
238 Disconnect();
239 break;
240 }
241 }
242 }
243 packet.Clear ();
244 return 0;
245}
246
247bool
Greg Claytond52d00f2011-07-16 03:19:08 +0000248CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet)
Greg Clayton363be3f2011-07-15 03:27:12 +0000249{
250 // Put the packet data into the buffer in a thread safe fashion
251 Mutex::Locker locker(m_bytes_mutex);
252
253 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
254
255 if (src && src_len > 0)
256 {
257 if (log && log->GetVerbose())
258 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000259 PacketStreamType log_strm;
Greg Clayton8d2ea282011-07-17 20:36:25 +0000260 DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS);
Greg Claytond52d00f2011-07-16 03:19:08 +0000261 log->Printf ("CommunicationKDP::%s adding %u bytes: %s",
Greg Clayton363be3f2011-07-15 03:27:12 +0000262 __FUNCTION__,
263 (uint32_t)src_len,
Greg Claytond52d00f2011-07-16 03:19:08 +0000264 log_strm.GetData());
Greg Clayton363be3f2011-07-15 03:27:12 +0000265 }
266 m_bytes.append ((const char *)src, src_len);
267 }
268
Greg Claytond52d00f2011-07-16 03:19:08 +0000269 // Make sure we at least have enough bytes for a packet header
270 const size_t bytes_available = m_bytes.size();
271 if (bytes_available >= 8)
Greg Clayton363be3f2011-07-15 03:27:12 +0000272 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000273 packet.SetData (&m_bytes[0], bytes_available, m_byte_order);
274 uint32_t offset = 0;
275 uint8_t reply_command = packet.GetU8(&offset);
276 switch (reply_command)
277 {
Greg Claytonea636012012-09-21 01:55:30 +0000278 case ePacketTypeRequest | KDP_EXCEPTION:
279 case ePacketTypeRequest | KDP_TERMINATION:
280 // We got an exception request, so be sure to send an ACK
281 {
282 PacketStreamType request_ack_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
283 // Set the reply but and make the ACK packet
284 request_ack_packet.PutHex8 (reply_command | ePacketTypeReply);
285 request_ack_packet.PutHex8 (packet.GetU8(&offset));
286 request_ack_packet.PutHex16 (packet.GetU16(&offset));
287 request_ack_packet.PutHex32 (packet.GetU32(&offset));
Greg Clayton3acaa922012-09-25 02:40:06 +0000288 m_is_running.SetValue(false, eBroadcastAlways);
Greg Claytonea636012012-09-21 01:55:30 +0000289 // Ack to the exception or termination
290 SendRequestPacketNoLock (request_ack_packet);
291 }
292 // Fall through to case below to get packet contents
Greg Clayton7b139222011-07-21 01:12:01 +0000293 case ePacketTypeReply | KDP_CONNECT:
294 case ePacketTypeReply | KDP_DISCONNECT:
295 case ePacketTypeReply | KDP_HOSTINFO:
296 case ePacketTypeReply | KDP_VERSION:
297 case ePacketTypeReply | KDP_MAXBYTES:
298 case ePacketTypeReply | KDP_READMEM:
299 case ePacketTypeReply | KDP_WRITEMEM:
300 case ePacketTypeReply | KDP_READREGS:
301 case ePacketTypeReply | KDP_WRITEREGS:
302 case ePacketTypeReply | KDP_LOAD:
303 case ePacketTypeReply | KDP_IMAGEPATH:
304 case ePacketTypeReply | KDP_SUSPEND:
305 case ePacketTypeReply | KDP_RESUMECPUS:
Greg Clayton7b139222011-07-21 01:12:01 +0000306 case ePacketTypeReply | KDP_BREAKPOINT_SET:
307 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE:
308 case ePacketTypeReply | KDP_REGIONS:
309 case ePacketTypeReply | KDP_REATTACH:
310 case ePacketTypeReply | KDP_HOSTREBOOT:
311 case ePacketTypeReply | KDP_READMEM64:
312 case ePacketTypeReply | KDP_WRITEMEM64:
313 case ePacketTypeReply | KDP_BREAKPOINT_SET64:
314 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64:
315 case ePacketTypeReply | KDP_KERNELVERSION:
Greg Claytond52d00f2011-07-16 03:19:08 +0000316 {
317 offset = 2;
318 const uint16_t length = packet.GetU16 (&offset);
319 if (length <= bytes_available)
320 {
321 // We have an entire packet ready, we need to copy the data
322 // bytes into a buffer that will be owned by the packet and
323 // erase the bytes from our communcation buffer "m_bytes"
324 packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length)));
325 m_bytes.erase (0, length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000326
327 if (log)
328 {
329 PacketStreamType log_strm;
Greg Clayton0fa51242011-07-19 03:57:15 +0000330 DumpPacket (log_strm, packet);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000331
Greg Clayton0fa51242011-07-19 03:57:15 +0000332 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton8d2ea282011-07-17 20:36:25 +0000333 }
Greg Claytond52d00f2011-07-16 03:19:08 +0000334 return true;
335 }
336 }
337 break;
338
339 default:
340 // Unrecognized reply command byte, erase this byte and try to get back on track
341 if (log)
342 log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
343 __FUNCTION__,
344 (uint8_t)m_bytes[0]);
345 m_bytes.erase(0, 1);
346 break;
347 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000348 }
349 packet.Clear();
350 return false;
351}
352
Greg Clayton1e5b0212011-07-15 16:31:38 +0000353
Greg Claytond52d00f2011-07-16 03:19:08 +0000354bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000355CommunicationKDP::SendRequestConnect (uint16_t reply_port,
356 uint16_t exc_port,
357 const char *greeting)
Greg Clayton1e5b0212011-07-15 16:31:38 +0000358{
Greg Clayton0fa51242011-07-19 03:57:15 +0000359 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000360 if (greeting == NULL)
361 greeting = "";
362
Greg Clayton7b139222011-07-21 01:12:01 +0000363 const CommandType command = KDP_CONNECT;
Greg Clayton8d2ea282011-07-17 20:36:25 +0000364 // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL
365 const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
Greg Claytond52d00f2011-07-16 03:19:08 +0000366 const uint32_t request_sequence_id = m_request_sequence_id;
367 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000368 // Always send connect ports as little endian
369 request_packet.SetByteOrder (eByteOrderLittle);
370 request_packet.PutHex16 (reply_port);
371 request_packet.PutHex16 (exc_port);
372 request_packet.SetByteOrder (m_byte_order);
373 request_packet.PutCString (greeting);
Greg Claytond52d00f2011-07-16 03:19:08 +0000374 DataExtractor reply_packet;
375 return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
Greg Clayton1e5b0212011-07-15 16:31:38 +0000376}
377
Greg Claytond52d00f2011-07-16 03:19:08 +0000378void
379CommunicationKDP::ClearKDPSettings ()
380{
381 m_request_sequence_id = 0;
382 m_kdp_version_version = 0;
383 m_kdp_version_feature = 0;
384 m_kdp_hostinfo_cpu_mask = 0;
385 m_kdp_hostinfo_cpu_type = 0;
386 m_kdp_hostinfo_cpu_subtype = 0;
387}
388
389bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000390CommunicationKDP::SendRequestReattach (uint16_t reply_port)
Greg Claytond52d00f2011-07-16 03:19:08 +0000391{
Greg Clayton0fa51242011-07-19 03:57:15 +0000392 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000393 const CommandType command = KDP_REATTACH;
Greg Claytond52d00f2011-07-16 03:19:08 +0000394 // Length is 8 bytes for the header plus 2 bytes for the reply UDP port
395 const uint32_t command_length = 8 + 2;
396 const uint32_t request_sequence_id = m_request_sequence_id;
397 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000398 // Always send connect ports as little endian
399 request_packet.SetByteOrder (eByteOrderLittle);
Greg Claytond52d00f2011-07-16 03:19:08 +0000400 request_packet.PutHex16(reply_port);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000401 request_packet.SetByteOrder (m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000402 DataExtractor reply_packet;
403 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
404 {
405 // Reset the sequence ID to zero for reattach
406 ClearKDPSettings ();
407 uint32_t offset = 4;
408 m_session_key = reply_packet.GetU32 (&offset);
409 return true;
410 }
411 return false;
412}
413
414uint32_t
415CommunicationKDP::GetVersion ()
416{
417 if (!VersionIsValid())
418 SendRequestVersion();
419 return m_kdp_version_version;
420}
421
422uint32_t
423CommunicationKDP::GetFeatureFlags ()
424{
425 if (!VersionIsValid())
426 SendRequestVersion();
427 return m_kdp_version_feature;
428}
429
430bool
431CommunicationKDP::SendRequestVersion ()
432{
Greg Clayton0fa51242011-07-19 03:57:15 +0000433 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000434 const CommandType command = KDP_VERSION;
Greg Claytond52d00f2011-07-16 03:19:08 +0000435 const uint32_t command_length = 8;
436 const uint32_t request_sequence_id = m_request_sequence_id;
437 MakeRequestPacketHeader (command, request_packet, command_length);
438 DataExtractor reply_packet;
439 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
440 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000441 uint32_t offset = 8;
442 m_kdp_version_version = reply_packet.GetU32 (&offset);
443 m_kdp_version_feature = reply_packet.GetU32 (&offset);
444 return true;
445 }
446 return false;
447}
448
Greg Clayton7b139222011-07-21 01:12:01 +0000449#if 0 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...
450const char *
451CommunicationKDP::GetImagePath ()
452{
453 if (m_image_path.empty())
454 SendRequestImagePath();
455 return m_image_path.c_str();
456}
457
458bool
459CommunicationKDP::SendRequestImagePath ()
460{
461 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
462 const CommandType command = KDP_IMAGEPATH;
463 const uint32_t command_length = 8;
464 const uint32_t request_sequence_id = m_request_sequence_id;
465 MakeRequestPacketHeader (command, request_packet, command_length);
466 DataExtractor reply_packet;
467 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
468 {
469 const char *path = reply_packet.PeekCStr(8);
470 if (path && path[0])
471 m_kernel_version.assign (path);
472 return true;
473 }
474 return false;
475}
476#endif
477
Greg Claytond52d00f2011-07-16 03:19:08 +0000478uint32_t
479CommunicationKDP::GetCPUMask ()
480{
481 if (!HostInfoIsValid())
482 SendRequestHostInfo();
483 return m_kdp_hostinfo_cpu_mask;
484}
485
486uint32_t
487CommunicationKDP::GetCPUType ()
488{
489 if (!HostInfoIsValid())
490 SendRequestHostInfo();
491 return m_kdp_hostinfo_cpu_type;
492}
493
494uint32_t
495CommunicationKDP::GetCPUSubtype ()
496{
497 if (!HostInfoIsValid())
498 SendRequestHostInfo();
499 return m_kdp_hostinfo_cpu_subtype;
500}
501
502bool
503CommunicationKDP::SendRequestHostInfo ()
504{
Greg Clayton0fa51242011-07-19 03:57:15 +0000505 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000506 const CommandType command = KDP_HOSTINFO;
Greg Claytond52d00f2011-07-16 03:19:08 +0000507 const uint32_t command_length = 8;
508 const uint32_t request_sequence_id = m_request_sequence_id;
509 MakeRequestPacketHeader (command, request_packet, command_length);
510 DataExtractor reply_packet;
511 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
512 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000513 uint32_t offset = 8;
Greg Clayton0fa51242011-07-19 03:57:15 +0000514 m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
515 m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
516 m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
517
518 ArchSpec kernel_arch;
519 kernel_arch.SetArchitecture (eArchTypeMachO,
520 m_kdp_hostinfo_cpu_type,
521 m_kdp_hostinfo_cpu_subtype);
522
523 m_addr_byte_size = kernel_arch.GetAddressByteSize();
524 m_byte_order = kernel_arch.GetByteOrder();
Greg Claytond52d00f2011-07-16 03:19:08 +0000525 return true;
526 }
527 return false;
528}
529
Greg Clayton234981a2011-07-20 03:41:06 +0000530const char *
531CommunicationKDP::GetKernelVersion ()
532{
533 if (m_kernel_version.empty())
534 SendRequestKernelVersion ();
535 return m_kernel_version.c_str();
536}
537
538bool
539CommunicationKDP::SendRequestKernelVersion ()
540{
541 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000542 const CommandType command = KDP_KERNELVERSION;
Greg Clayton234981a2011-07-20 03:41:06 +0000543 const uint32_t command_length = 8;
544 const uint32_t request_sequence_id = m_request_sequence_id;
545 MakeRequestPacketHeader (command, request_packet, command_length);
546 DataExtractor reply_packet;
547 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
548 {
549 const char *kernel_version_cstr = reply_packet.PeekCStr(8);
550 if (kernel_version_cstr && kernel_version_cstr[0])
551 m_kernel_version.assign (kernel_version_cstr);
552 return true;
553 }
554 return false;
555}
556
Greg Claytond52d00f2011-07-16 03:19:08 +0000557bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000558CommunicationKDP::SendRequestDisconnect ()
Greg Clayton1e5b0212011-07-15 16:31:38 +0000559{
Greg Clayton0fa51242011-07-19 03:57:15 +0000560 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000561 const CommandType command = KDP_DISCONNECT;
Greg Claytond52d00f2011-07-16 03:19:08 +0000562 const uint32_t command_length = 8;
563 const uint32_t request_sequence_id = m_request_sequence_id;
564 MakeRequestPacketHeader (command, request_packet, command_length);
565 DataExtractor reply_packet;
566 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
567 {
568 // Are we supposed to get a reply for disconnect?
569 }
570 ClearKDPSettings ();
571 return true;
Greg Clayton1e5b0212011-07-15 16:31:38 +0000572}
573
Greg Clayton0fa51242011-07-19 03:57:15 +0000574uint32_t
575CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr,
576 void *dst,
577 uint32_t dst_len,
578 Error &error)
579{
580 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
581 bool use_64 = (GetVersion() >= 11);
582 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +0000583 const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM;
Greg Clayton0fa51242011-07-19 03:57:15 +0000584 // Size is header + address size + uint32_t length
585 const uint32_t command_length = 8 + command_addr_byte_size + 4;
586 const uint32_t request_sequence_id = m_request_sequence_id;
587 MakeRequestPacketHeader (command, request_packet, command_length);
588 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
589 request_packet.PutHex32 (dst_len);
590 DataExtractor reply_packet;
591 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
592 {
Greg Clayton0fa51242011-07-19 03:57:15 +0000593 uint32_t offset = 8;
594 uint32_t kdp_error = reply_packet.GetU32 (&offset);
595 uint32_t src_len = reply_packet.GetByteSize() - 12;
596
597 if (src_len > 0)
598 {
599 const void *src = reply_packet.GetData(&offset, src_len);
600 if (src)
601 {
602 ::memcpy (dst, src, src_len);
603 error.Clear();
604 return src_len;
605 }
606 }
607 if (kdp_error)
608 error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error);
609 else
610 error.SetErrorString ("kdp read memory failed");
611 }
612 return 0;
613}
614
Greg Claytonec15f502011-07-20 01:32:50 +0000615
616uint32_t
617CommunicationKDP::SendRequestWriteMemory (lldb::addr_t addr,
618 const void *src,
619 uint32_t src_len,
620 Error &error)
621{
622 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
623 bool use_64 = (GetVersion() >= 11);
624 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +0000625 const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM;
Greg Claytonec15f502011-07-20 01:32:50 +0000626 // Size is header + address size + uint32_t length
627 const uint32_t command_length = 8 + command_addr_byte_size + 4;
628 const uint32_t request_sequence_id = m_request_sequence_id;
629 MakeRequestPacketHeader (command, request_packet, command_length);
630 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
631 request_packet.PutHex32 (src_len);
632 request_packet.PutBytesAsRawHex8(src, src_len);
633
634 DataExtractor reply_packet;
635 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
636 {
637 uint32_t offset = 8;
638 uint32_t kdp_error = reply_packet.GetU32 (&offset);
639 if (kdp_error)
640 error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error);
641 else
642 {
643 error.Clear();
644 return src_len;
645 }
646 }
647 return 0;
648}
649
Greg Clayton0fa51242011-07-19 03:57:15 +0000650const char *
651CommunicationKDP::GetCommandAsCString (uint8_t command)
652{
653 switch (command)
654 {
Greg Clayton7b139222011-07-21 01:12:01 +0000655 case KDP_CONNECT: return "KDP_CONNECT";
656 case KDP_DISCONNECT: return "KDP_DISCONNECT";
657 case KDP_HOSTINFO: return "KDP_HOSTINFO";
658 case KDP_VERSION: return "KDP_VERSION";
659 case KDP_MAXBYTES: return "KDP_MAXBYTES";
660 case KDP_READMEM: return "KDP_READMEM";
661 case KDP_WRITEMEM: return "KDP_WRITEMEM";
662 case KDP_READREGS: return "KDP_READREGS";
663 case KDP_WRITEREGS: return "KDP_WRITEREGS";
664 case KDP_LOAD: return "KDP_LOAD";
665 case KDP_IMAGEPATH: return "KDP_IMAGEPATH";
666 case KDP_SUSPEND: return "KDP_SUSPEND";
667 case KDP_RESUMECPUS: return "KDP_RESUMECPUS";
668 case KDP_EXCEPTION: return "KDP_EXCEPTION";
669 case KDP_TERMINATION: return "KDP_TERMINATION";
670 case KDP_BREAKPOINT_SET: return "KDP_BREAKPOINT_SET";
671 case KDP_BREAKPOINT_REMOVE: return "KDP_BREAKPOINT_REMOVE";
672 case KDP_REGIONS: return "KDP_REGIONS";
673 case KDP_REATTACH: return "KDP_REATTACH";
674 case KDP_HOSTREBOOT: return "KDP_HOSTREBOOT";
675 case KDP_READMEM64: return "KDP_READMEM64";
676 case KDP_WRITEMEM64: return "KDP_WRITEMEM64";
677 case KDP_BREAKPOINT_SET64: return "KDP_BREAKPOINT64_SET";
678 case KDP_BREAKPOINT_REMOVE64: return "KDP_BREAKPOINT64_REMOVE";
679 case KDP_KERNELVERSION: return "KDP_KERNELVERSION";
Greg Clayton0fa51242011-07-19 03:57:15 +0000680 }
681 return NULL;
682}
683
684void
685CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len)
686{
687 DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size);
688 DumpPacket (s, extractor);
689}
690
691void
692CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
693{
694 const char *error_desc = NULL;
695 if (packet.GetByteSize() < 8)
696 {
697 error_desc = "error: invalid packet (too short): ";
698 }
699 else
700 {
701 uint32_t offset = 0;
702 const uint8_t first_packet_byte = packet.GetU8 (&offset);
703 const uint8_t sequence_id = packet.GetU8 (&offset);
704 const uint16_t length = packet.GetU16 (&offset);
705 const uint32_t key = packet.GetU32 (&offset);
706 const CommandType command = ExtractCommand (first_packet_byte);
707 const char *command_name = GetCommandAsCString (command);
708 if (command_name)
709 {
710 const bool is_reply = ExtractIsReply(first_packet_byte);
Greg Clayton3acaa922012-09-25 02:40:06 +0000711 s.Printf ("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ",
712 IsRunning(),
713 is_reply ? "<--" : "-->",
714 command_name,
715 first_packet_byte,
Greg Clayton0fa51242011-07-19 03:57:15 +0000716 sequence_id,
717 length,
Greg Clayton3acaa922012-09-25 02:40:06 +0000718 key);
Greg Clayton0fa51242011-07-19 03:57:15 +0000719
720 if (is_reply)
721 {
722 // Dump request reply packets
723 switch (command)
724 {
Greg Claytonec15f502011-07-20 01:32:50 +0000725 // Commands that return a single 32 bit error
Greg Clayton7b139222011-07-21 01:12:01 +0000726 case KDP_CONNECT:
727 case KDP_WRITEMEM:
728 case KDP_WRITEMEM64:
729 case KDP_BREAKPOINT_SET:
730 case KDP_BREAKPOINT_REMOVE:
731 case KDP_BREAKPOINT_SET64:
732 case KDP_BREAKPOINT_REMOVE64:
733 case KDP_WRITEREGS:
734 case KDP_LOAD:
Greg Clayton0fa51242011-07-19 03:57:15 +0000735 {
736 const uint32_t error = packet.GetU32 (&offset);
737 s.Printf(" (error=0x%8.8x)", error);
738 }
739 break;
740
Greg Clayton7b139222011-07-21 01:12:01 +0000741 case KDP_DISCONNECT:
742 case KDP_REATTACH:
743 case KDP_HOSTREBOOT:
744 case KDP_SUSPEND:
745 case KDP_RESUMECPUS:
746 case KDP_EXCEPTION:
747 case KDP_TERMINATION:
Greg Clayton0fa51242011-07-19 03:57:15 +0000748 // No return value for the reply, just the header to ack
Greg Claytonec15f502011-07-20 01:32:50 +0000749 s.PutCString(" ()");
Greg Clayton0fa51242011-07-19 03:57:15 +0000750 break;
751
Greg Clayton7b139222011-07-21 01:12:01 +0000752 case KDP_HOSTINFO:
Greg Clayton0fa51242011-07-19 03:57:15 +0000753 {
754 const uint32_t cpu_mask = packet.GetU32 (&offset);
755 const uint32_t cpu_type = packet.GetU32 (&offset);
756 const uint32_t cpu_subtype = packet.GetU32 (&offset);
757 s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype);
758 }
759 break;
760
Greg Clayton7b139222011-07-21 01:12:01 +0000761 case KDP_VERSION:
Greg Clayton0fa51242011-07-19 03:57:15 +0000762 {
763 const uint32_t version = packet.GetU32 (&offset);
764 const uint32_t feature = packet.GetU32 (&offset);
765 s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
766 }
767 break;
768
Greg Clayton7b139222011-07-21 01:12:01 +0000769 case KDP_REGIONS:
Greg Clayton0fa51242011-07-19 03:57:15 +0000770 {
771 const uint32_t region_count = packet.GetU32 (&offset);
772 s.Printf(" (count = %u", region_count);
773 for (uint32_t i=0; i<region_count; ++i)
774 {
775 const addr_t region_addr = packet.GetPointer (&offset);
776 const uint32_t region_size = packet.GetU32 (&offset);
777 const uint32_t region_prot = packet.GetU32 (&offset);
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000778 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 +0000779 }
780 }
781 break;
782
Greg Clayton7b139222011-07-21 01:12:01 +0000783 case KDP_READMEM:
784 case KDP_READMEM64:
Greg Clayton0fa51242011-07-19 03:57:15 +0000785 {
786 const uint32_t error = packet.GetU32 (&offset);
Greg Claytonec15f502011-07-20 01:32:50 +0000787 const uint32_t count = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000788 s.Printf(" (error = 0x%8.8x:\n", error);
Greg Clayton0fa51242011-07-19 03:57:15 +0000789 if (count > 0)
Greg Clayton234981a2011-07-20 03:41:06 +0000790 packet.Dump (&s, // Stream to dump to
791 offset, // Offset within "packet"
792 eFormatBytesWithASCII, // Format to use
793 1, // Size of each item in bytes
794 count, // Number of items
795 16, // Number per line
796 m_last_read_memory_addr, // Don't show addresses before each line
797 0, 0); // No bitfields
Greg Clayton0fa51242011-07-19 03:57:15 +0000798 }
799 break;
800
Greg Clayton7b139222011-07-21 01:12:01 +0000801 case KDP_READREGS:
Greg Claytonec15f502011-07-20 01:32:50 +0000802 {
803 const uint32_t error = packet.GetU32 (&offset);
804 const uint32_t count = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000805 s.Printf(" (error = 0x%8.8x regs:\n", error);
Greg Claytonec15f502011-07-20 01:32:50 +0000806 if (count > 0)
807 packet.Dump (&s, // Stream to dump to
808 offset, // Offset within "packet"
809 eFormatHex, // Format to use
810 m_addr_byte_size, // Size of each item in bytes
811 count / m_addr_byte_size, // Number of items
812 16 / m_addr_byte_size, // Number per line
813 LLDB_INVALID_ADDRESS, // Don't show addresses before each line
814 0, 0); // No bitfields
815 }
816 break;
817
Greg Clayton7b139222011-07-21 01:12:01 +0000818 case KDP_KERNELVERSION:
Greg Clayton234981a2011-07-20 03:41:06 +0000819 {
820 const char *kernel_version = packet.PeekCStr(8);
821 s.Printf(" (version = \"%s\")", kernel_version);
822 }
823 break;
824
Greg Clayton7b139222011-07-21 01:12:01 +0000825 case KDP_MAXBYTES:
Greg Clayton234981a2011-07-20 03:41:06 +0000826 {
827 const uint32_t max_bytes = packet.GetU32 (&offset);
828 s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes);
829 }
830 break;
Greg Clayton7b139222011-07-21 01:12:01 +0000831 case KDP_IMAGEPATH:
Greg Clayton234981a2011-07-20 03:41:06 +0000832 {
833 const char *path = packet.GetCStr(&offset);
834 s.Printf(" (path = \"%s\")", path);
835 }
836 break;
837 default:
Greg Claytonec15f502011-07-20 01:32:50 +0000838 s.Printf(" (add support for dumping this packet reply!!!");
Greg Clayton0fa51242011-07-19 03:57:15 +0000839 break;
840
841 }
842 }
843 else
844 {
845 // Dump request packets
846 switch (command)
847 {
Greg Clayton7b139222011-07-21 01:12:01 +0000848 case KDP_CONNECT:
Greg Clayton0fa51242011-07-19 03:57:15 +0000849 {
850 const uint16_t reply_port = packet.GetU16 (&offset);
851 const uint16_t exc_port = packet.GetU16 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000852 s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset));
Greg Clayton0fa51242011-07-19 03:57:15 +0000853 }
854 break;
855
Greg Clayton7b139222011-07-21 01:12:01 +0000856 case KDP_DISCONNECT:
857 case KDP_HOSTREBOOT:
858 case KDP_HOSTINFO:
859 case KDP_VERSION:
860 case KDP_REGIONS:
861 case KDP_KERNELVERSION:
862 case KDP_MAXBYTES:
863 case KDP_IMAGEPATH:
864 case KDP_SUSPEND:
Greg Clayton0fa51242011-07-19 03:57:15 +0000865 // No args, just the header in the request...
Greg Clayton234981a2011-07-20 03:41:06 +0000866 s.PutCString(" ()");
867 break;
868
Greg Clayton7b139222011-07-21 01:12:01 +0000869 case KDP_RESUMECPUS:
Greg Clayton234981a2011-07-20 03:41:06 +0000870 {
871 const uint32_t cpu_mask = packet.GetU32 (&offset);
872 s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask);
873 }
Greg Clayton0fa51242011-07-19 03:57:15 +0000874 break;
875
Greg Clayton7b139222011-07-21 01:12:01 +0000876 case KDP_READMEM:
Greg Clayton0fa51242011-07-19 03:57:15 +0000877 {
878 const uint32_t addr = packet.GetU32 (&offset);
879 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000880 s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size);
Greg Clayton234981a2011-07-20 03:41:06 +0000881 m_last_read_memory_addr = addr;
Greg Clayton0fa51242011-07-19 03:57:15 +0000882 }
883 break;
884
Greg Clayton7b139222011-07-21 01:12:01 +0000885 case KDP_WRITEMEM:
Greg Claytonec15f502011-07-20 01:32:50 +0000886 {
887 const uint32_t addr = packet.GetU32 (&offset);
888 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000889 s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size);
Greg Claytonec15f502011-07-20 01:32:50 +0000890 if (size > 0)
891 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
892 }
893 break;
894
Greg Clayton7b139222011-07-21 01:12:01 +0000895 case KDP_READMEM64:
Greg Clayton0fa51242011-07-19 03:57:15 +0000896 {
897 const uint64_t addr = packet.GetU64 (&offset);
898 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000899 s.Printf(" (addr = 0x%16.16llx, size = %u)", addr, size);
Greg Clayton234981a2011-07-20 03:41:06 +0000900 m_last_read_memory_addr = addr;
Greg Clayton0fa51242011-07-19 03:57:15 +0000901 }
902 break;
903
Greg Clayton7b139222011-07-21 01:12:01 +0000904 case KDP_WRITEMEM64:
Greg Claytonec15f502011-07-20 01:32:50 +0000905 {
906 const uint64_t addr = packet.GetU64 (&offset);
907 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000908 s.Printf(" (addr = 0x%16.16llx, size = %u, bytes = \n", addr, size);
Greg Claytonec15f502011-07-20 01:32:50 +0000909 if (size > 0)
910 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
911 }
912 break;
913
Greg Clayton7b139222011-07-21 01:12:01 +0000914 case KDP_READREGS:
Greg Clayton0fa51242011-07-19 03:57:15 +0000915 {
916 const uint32_t cpu = packet.GetU32 (&offset);
917 const uint32_t flavor = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000918 s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor);
Greg Clayton0fa51242011-07-19 03:57:15 +0000919 }
920 break;
921
Greg Clayton7b139222011-07-21 01:12:01 +0000922 case KDP_WRITEREGS:
Greg Claytonec15f502011-07-20 01:32:50 +0000923 {
924 const uint32_t cpu = packet.GetU32 (&offset);
925 const uint32_t flavor = packet.GetU32 (&offset);
926 const uint32_t nbytes = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000927 s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor);
Greg Claytonec15f502011-07-20 01:32:50 +0000928 if (nbytes > 0)
929 packet.Dump (&s, // Stream to dump to
930 offset, // Offset within "packet"
931 eFormatHex, // Format to use
932 m_addr_byte_size, // Size of each item in bytes
933 nbytes / m_addr_byte_size, // Number of items
934 16 / m_addr_byte_size, // Number per line
935 LLDB_INVALID_ADDRESS, // Don't show addresses before each line
936 0, 0); // No bitfields
937 }
938 break;
939
Greg Claytonec15f502011-07-20 01:32:50 +0000940
Greg Clayton7b139222011-07-21 01:12:01 +0000941 case KDP_BREAKPOINT_SET:
942 case KDP_BREAKPOINT_REMOVE:
Greg Clayton234981a2011-07-20 03:41:06 +0000943 {
944 const uint32_t addr = packet.GetU32 (&offset);
945 s.Printf(" (addr = 0x%8.8x)", addr);
946 }
947 break;
948
Greg Clayton7b139222011-07-21 01:12:01 +0000949 case KDP_BREAKPOINT_SET64:
950 case KDP_BREAKPOINT_REMOVE64:
Greg Clayton234981a2011-07-20 03:41:06 +0000951 {
952 const uint64_t addr = packet.GetU64 (&offset);
953 s.Printf(" (addr = 0x%16.16llx)", addr);
954 }
955 break;
956
957
Greg Clayton7b139222011-07-21 01:12:01 +0000958 case KDP_LOAD:
Greg Clayton234981a2011-07-20 03:41:06 +0000959 {
960 const char *path = packet.GetCStr(&offset);
961 s.Printf(" (path = \"%s\")", path);
962 }
963 break;
964
Greg Clayton7b139222011-07-21 01:12:01 +0000965 case KDP_EXCEPTION:
Greg Clayton234981a2011-07-20 03:41:06 +0000966 {
967 const uint32_t count = packet.GetU32 (&offset);
968
Greg Clayton234981a2011-07-20 03:41:06 +0000969 for (uint32_t i=0; i<count; ++i)
970 {
971 const uint32_t cpu = packet.GetU32 (&offset);
972 const uint32_t exc = packet.GetU32 (&offset);
973 const uint32_t code = packet.GetU32 (&offset);
974 const uint32_t subcode = packet.GetU32 (&offset);
975 const char *exc_cstr = NULL;
976 switch (exc)
977 {
978 case 1: exc_cstr = "EXC_BAD_ACCESS"; break;
979 case 2: exc_cstr = "EXC_BAD_INSTRUCTION"; break;
980 case 3: exc_cstr = "EXC_ARITHMETIC"; break;
981 case 4: exc_cstr = "EXC_EMULATION"; break;
982 case 5: exc_cstr = "EXC_SOFTWARE"; break;
983 case 6: exc_cstr = "EXC_BREAKPOINT"; break;
984 case 7: exc_cstr = "EXC_SYSCALL"; break;
985 case 8: exc_cstr = "EXC_MACH_SYSCALL"; break;
986 case 9: exc_cstr = "EXC_RPC_ALERT"; break;
987 case 10: exc_cstr = "EXC_CRASH"; break;
988 default:
989 break;
990 }
991
Greg Clayton3acaa922012-09-25 02:40:06 +0000992 s.Printf ("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)} ",
Greg Clayton234981a2011-07-20 03:41:06 +0000993 cpu, exc_cstr, exc, code, code, subcode, subcode);
994 }
995 }
996 break;
997
Greg Clayton7b139222011-07-21 01:12:01 +0000998 case KDP_TERMINATION:
Greg Clayton234981a2011-07-20 03:41:06 +0000999 {
1000 const uint32_t term_code = packet.GetU32 (&offset);
1001 const uint32_t exit_code = packet.GetU32 (&offset);
1002 s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code);
1003 }
Greg Clayton0fa51242011-07-19 03:57:15 +00001004 break;
1005
Greg Clayton7b139222011-07-21 01:12:01 +00001006 case KDP_REATTACH:
Greg Clayton0fa51242011-07-19 03:57:15 +00001007 {
1008 const uint16_t reply_port = packet.GetU16 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +00001009 s.Printf(" (reply_port = %u)", reply_port);
Greg Clayton0fa51242011-07-19 03:57:15 +00001010 }
1011 break;
Greg Clayton0fa51242011-07-19 03:57:15 +00001012 }
1013 }
1014 }
1015 else
1016 {
1017 error_desc = "error: invalid packet command: ";
1018 }
1019 }
1020
1021 if (error_desc)
1022 {
1023 s.PutCString (error_desc);
1024
1025 packet.Dump (&s, // Stream to dump to
1026 0, // Offset into "packet"
1027 eFormatBytes, // Dump as hex bytes
1028 1, // Size of each item is 1 for single bytes
1029 packet.GetByteSize(), // Number of bytes
1030 UINT32_MAX, // Num bytes per line
1031 LLDB_INVALID_ADDRESS, // Base address
1032 0, 0); // Bitfield info set to not do anything bitfield related
1033 }
1034}
1035
1036uint32_t
1037CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
1038 uint32_t flavor,
Greg Claytonea636012012-09-21 01:55:30 +00001039 void *dst,
Greg Clayton0fa51242011-07-19 03:57:15 +00001040 uint32_t dst_len,
1041 Error &error)
1042{
1043 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001044 const CommandType command = KDP_READREGS;
Greg Clayton0fa51242011-07-19 03:57:15 +00001045 // Size is header + 4 byte cpu and 4 byte flavor
1046 const uint32_t command_length = 8 + 4 + 4;
1047 const uint32_t request_sequence_id = m_request_sequence_id;
1048 MakeRequestPacketHeader (command, request_packet, command_length);
1049 request_packet.PutHex32 (cpu);
1050 request_packet.PutHex32 (flavor);
1051 DataExtractor reply_packet;
1052 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1053 {
Greg Clayton0fa51242011-07-19 03:57:15 +00001054 uint32_t offset = 8;
1055 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1056 uint32_t src_len = reply_packet.GetByteSize() - 12;
1057
1058 if (src_len > 0)
1059 {
1060 const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
1061 const void *src = reply_packet.GetData(&offset, bytes_to_copy);
1062 if (src)
1063 {
1064 ::memcpy (dst, src, bytes_to_copy);
1065 error.Clear();
1066 // Return the number of bytes we could have returned regardless if
1067 // we copied them or not, just so we know when things don't match up
Greg Claytonea636012012-09-21 01:55:30 +00001068 return src_len;
Greg Clayton0fa51242011-07-19 03:57:15 +00001069 }
1070 }
1071 if (kdp_error)
1072 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
1073 else
1074 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
1075 }
1076 return 0;
1077}
1078
Greg Claytonea636012012-09-21 01:55:30 +00001079uint32_t
1080CommunicationKDP::SendRequestWriteRegisters (uint32_t cpu,
1081 uint32_t flavor,
1082 const void *src,
1083 uint32_t src_len,
1084 Error &error)
1085{
1086 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1087 const CommandType command = KDP_WRITEREGS;
1088 // Size is header + 4 byte cpu and 4 byte flavor
Greg Clayton3acaa922012-09-25 02:40:06 +00001089 const uint32_t command_length = 8 + 4 + 4 + src_len;
Greg Claytonea636012012-09-21 01:55:30 +00001090 const uint32_t request_sequence_id = m_request_sequence_id;
1091 MakeRequestPacketHeader (command, request_packet, command_length);
1092 request_packet.PutHex32 (cpu);
1093 request_packet.PutHex32 (flavor);
1094 request_packet.Write(src, src_len);
1095 DataExtractor reply_packet;
1096 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1097 {
1098 uint32_t offset = 8;
1099 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1100 if (kdp_error == 0)
1101 return src_len;
1102 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
1103 }
1104 return 0;
1105}
1106
Greg Clayton234981a2011-07-20 03:41:06 +00001107
1108bool
Greg Clayton3acaa922012-09-25 02:40:06 +00001109CommunicationKDP::SendRequestResume ()
Greg Clayton234981a2011-07-20 03:41:06 +00001110{
Greg Clayton234981a2011-07-20 03:41:06 +00001111 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001112 const CommandType command = KDP_RESUMECPUS;
Greg Clayton234981a2011-07-20 03:41:06 +00001113 const uint32_t command_length = 12;
1114 const uint32_t request_sequence_id = m_request_sequence_id;
1115 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton3acaa922012-09-25 02:40:06 +00001116 request_packet.PutHex32(GetCPUMask());
Greg Clayton234981a2011-07-20 03:41:06 +00001117
1118 DataExtractor reply_packet;
1119 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1120 return true;
1121 return false;
1122}
1123
1124bool
1125CommunicationKDP::SendRequestBreakpoint (bool set, addr_t addr)
1126{
1127 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1128 bool use_64 = (GetVersion() >= 11);
1129 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +00001130 const CommandType command = set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET ):
1131 (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE);
Greg Clayton234981a2011-07-20 03:41:06 +00001132
1133 const uint32_t command_length = 8 + command_addr_byte_size;
1134 const uint32_t request_sequence_id = m_request_sequence_id;
1135 MakeRequestPacketHeader (command, request_packet, command_length);
1136 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
1137
1138 DataExtractor reply_packet;
1139 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
Greg Clayton1bc04ed2011-07-29 22:26:36 +00001140 {
1141 uint32_t offset = 8;
1142 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1143 if (kdp_error == 0)
1144 return true;
1145 }
Greg Clayton234981a2011-07-20 03:41:06 +00001146 return false;
1147}
1148
1149bool
1150CommunicationKDP::SendRequestSuspend ()
1151{
1152 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001153 const CommandType command = KDP_SUSPEND;
Greg Clayton234981a2011-07-20 03:41:06 +00001154 const uint32_t command_length = 8;
1155 const uint32_t request_sequence_id = m_request_sequence_id;
1156 MakeRequestPacketHeader (command, request_packet, command_length);
1157 DataExtractor reply_packet;
1158 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1159 return true;
1160 return false;
1161}
1162