blob: 0b49f1fc27956302a51bd6e0ec4e75ed8b02d839 [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)
148 log->Printf ("error: failed to send packet entire packet %zu of %zu bytes sent", bytes_written, packet_size);
149 }
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)
192 log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu",
193 __PRETTY_FUNCTION__,
194 timeout_usec,
195 Communication::ConnectionStatusAsCString (status),
196 error.AsCString(),
197 bytes_read);
198
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 Clayton7b139222011-07-21 01:12:01 +0000259 case ePacketTypeReply | KDP_CONNECT:
260 case ePacketTypeReply | KDP_DISCONNECT:
261 case ePacketTypeReply | KDP_HOSTINFO:
262 case ePacketTypeReply | KDP_VERSION:
263 case ePacketTypeReply | KDP_MAXBYTES:
264 case ePacketTypeReply | KDP_READMEM:
265 case ePacketTypeReply | KDP_WRITEMEM:
266 case ePacketTypeReply | KDP_READREGS:
267 case ePacketTypeReply | KDP_WRITEREGS:
268 case ePacketTypeReply | KDP_LOAD:
269 case ePacketTypeReply | KDP_IMAGEPATH:
270 case ePacketTypeReply | KDP_SUSPEND:
271 case ePacketTypeReply | KDP_RESUMECPUS:
272 case ePacketTypeReply | KDP_EXCEPTION:
273 case ePacketTypeReply | KDP_TERMINATION:
274 case ePacketTypeReply | KDP_BREAKPOINT_SET:
275 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE:
276 case ePacketTypeReply | KDP_REGIONS:
277 case ePacketTypeReply | KDP_REATTACH:
278 case ePacketTypeReply | KDP_HOSTREBOOT:
279 case ePacketTypeReply | KDP_READMEM64:
280 case ePacketTypeReply | KDP_WRITEMEM64:
281 case ePacketTypeReply | KDP_BREAKPOINT_SET64:
282 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64:
283 case ePacketTypeReply | KDP_KERNELVERSION:
Greg Claytond52d00f2011-07-16 03:19:08 +0000284 {
285 offset = 2;
286 const uint16_t length = packet.GetU16 (&offset);
287 if (length <= bytes_available)
288 {
289 // We have an entire packet ready, we need to copy the data
290 // bytes into a buffer that will be owned by the packet and
291 // erase the bytes from our communcation buffer "m_bytes"
292 packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length)));
293 m_bytes.erase (0, length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000294
295 if (log)
296 {
297 PacketStreamType log_strm;
Greg Clayton0fa51242011-07-19 03:57:15 +0000298 DumpPacket (log_strm, packet);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000299
Greg Clayton0fa51242011-07-19 03:57:15 +0000300 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton8d2ea282011-07-17 20:36:25 +0000301 }
Greg Claytond52d00f2011-07-16 03:19:08 +0000302 return true;
303 }
304 }
305 break;
306
307 default:
308 // Unrecognized reply command byte, erase this byte and try to get back on track
309 if (log)
310 log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
311 __FUNCTION__,
312 (uint8_t)m_bytes[0]);
313 m_bytes.erase(0, 1);
314 break;
315 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000316 }
317 packet.Clear();
318 return false;
319}
320
Greg Clayton1e5b0212011-07-15 16:31:38 +0000321
Greg Claytond52d00f2011-07-16 03:19:08 +0000322bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000323CommunicationKDP::SendRequestConnect (uint16_t reply_port,
324 uint16_t exc_port,
325 const char *greeting)
Greg Clayton1e5b0212011-07-15 16:31:38 +0000326{
Greg Clayton0fa51242011-07-19 03:57:15 +0000327 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000328 if (greeting == NULL)
329 greeting = "";
330
Greg Clayton7b139222011-07-21 01:12:01 +0000331 const CommandType command = KDP_CONNECT;
Greg Clayton8d2ea282011-07-17 20:36:25 +0000332 // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL
333 const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
Greg Claytond52d00f2011-07-16 03:19:08 +0000334 const uint32_t request_sequence_id = m_request_sequence_id;
335 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000336 // Always send connect ports as little endian
337 request_packet.SetByteOrder (eByteOrderLittle);
338 request_packet.PutHex16 (reply_port);
339 request_packet.PutHex16 (exc_port);
340 request_packet.SetByteOrder (m_byte_order);
341 request_packet.PutCString (greeting);
Greg Claytond52d00f2011-07-16 03:19:08 +0000342 DataExtractor reply_packet;
343 return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
Greg Clayton1e5b0212011-07-15 16:31:38 +0000344}
345
Greg Claytond52d00f2011-07-16 03:19:08 +0000346void
347CommunicationKDP::ClearKDPSettings ()
348{
349 m_request_sequence_id = 0;
350 m_kdp_version_version = 0;
351 m_kdp_version_feature = 0;
352 m_kdp_hostinfo_cpu_mask = 0;
353 m_kdp_hostinfo_cpu_type = 0;
354 m_kdp_hostinfo_cpu_subtype = 0;
355}
356
357bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000358CommunicationKDP::SendRequestReattach (uint16_t reply_port)
Greg Claytond52d00f2011-07-16 03:19:08 +0000359{
Greg Clayton0fa51242011-07-19 03:57:15 +0000360 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000361 const CommandType command = KDP_REATTACH;
Greg Claytond52d00f2011-07-16 03:19:08 +0000362 // Length is 8 bytes for the header plus 2 bytes for the reply UDP port
363 const uint32_t command_length = 8 + 2;
364 const uint32_t request_sequence_id = m_request_sequence_id;
365 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000366 // Always send connect ports as little endian
367 request_packet.SetByteOrder (eByteOrderLittle);
Greg Claytond52d00f2011-07-16 03:19:08 +0000368 request_packet.PutHex16(reply_port);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000369 request_packet.SetByteOrder (m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000370 DataExtractor reply_packet;
371 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
372 {
373 // Reset the sequence ID to zero for reattach
374 ClearKDPSettings ();
375 uint32_t offset = 4;
376 m_session_key = reply_packet.GetU32 (&offset);
377 return true;
378 }
379 return false;
380}
381
382uint32_t
383CommunicationKDP::GetVersion ()
384{
385 if (!VersionIsValid())
386 SendRequestVersion();
387 return m_kdp_version_version;
388}
389
390uint32_t
391CommunicationKDP::GetFeatureFlags ()
392{
393 if (!VersionIsValid())
394 SendRequestVersion();
395 return m_kdp_version_feature;
396}
397
398bool
399CommunicationKDP::SendRequestVersion ()
400{
Greg Clayton0fa51242011-07-19 03:57:15 +0000401 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000402 const CommandType command = KDP_VERSION;
Greg Claytond52d00f2011-07-16 03:19:08 +0000403 const uint32_t command_length = 8;
404 const uint32_t request_sequence_id = m_request_sequence_id;
405 MakeRequestPacketHeader (command, request_packet, command_length);
406 DataExtractor reply_packet;
407 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
408 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000409 uint32_t offset = 8;
410 m_kdp_version_version = reply_packet.GetU32 (&offset);
411 m_kdp_version_feature = reply_packet.GetU32 (&offset);
412 return true;
413 }
414 return false;
415}
416
Greg Clayton7b139222011-07-21 01:12:01 +0000417#if 0 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...
418const char *
419CommunicationKDP::GetImagePath ()
420{
421 if (m_image_path.empty())
422 SendRequestImagePath();
423 return m_image_path.c_str();
424}
425
426bool
427CommunicationKDP::SendRequestImagePath ()
428{
429 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
430 const CommandType command = KDP_IMAGEPATH;
431 const uint32_t command_length = 8;
432 const uint32_t request_sequence_id = m_request_sequence_id;
433 MakeRequestPacketHeader (command, request_packet, command_length);
434 DataExtractor reply_packet;
435 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
436 {
437 const char *path = reply_packet.PeekCStr(8);
438 if (path && path[0])
439 m_kernel_version.assign (path);
440 return true;
441 }
442 return false;
443}
444#endif
445
Greg Claytond52d00f2011-07-16 03:19:08 +0000446uint32_t
447CommunicationKDP::GetCPUMask ()
448{
449 if (!HostInfoIsValid())
450 SendRequestHostInfo();
451 return m_kdp_hostinfo_cpu_mask;
452}
453
454uint32_t
455CommunicationKDP::GetCPUType ()
456{
457 if (!HostInfoIsValid())
458 SendRequestHostInfo();
459 return m_kdp_hostinfo_cpu_type;
460}
461
462uint32_t
463CommunicationKDP::GetCPUSubtype ()
464{
465 if (!HostInfoIsValid())
466 SendRequestHostInfo();
467 return m_kdp_hostinfo_cpu_subtype;
468}
469
470bool
471CommunicationKDP::SendRequestHostInfo ()
472{
Greg Clayton0fa51242011-07-19 03:57:15 +0000473 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000474 const CommandType command = KDP_HOSTINFO;
Greg Claytond52d00f2011-07-16 03:19:08 +0000475 const uint32_t command_length = 8;
476 const uint32_t request_sequence_id = m_request_sequence_id;
477 MakeRequestPacketHeader (command, request_packet, command_length);
478 DataExtractor reply_packet;
479 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
480 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000481 uint32_t offset = 8;
Greg Clayton0fa51242011-07-19 03:57:15 +0000482 m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
483 m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
484 m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
485
486 ArchSpec kernel_arch;
487 kernel_arch.SetArchitecture (eArchTypeMachO,
488 m_kdp_hostinfo_cpu_type,
489 m_kdp_hostinfo_cpu_subtype);
490
491 m_addr_byte_size = kernel_arch.GetAddressByteSize();
492 m_byte_order = kernel_arch.GetByteOrder();
Greg Claytond52d00f2011-07-16 03:19:08 +0000493 return true;
494 }
495 return false;
496}
497
Greg Clayton234981a2011-07-20 03:41:06 +0000498const char *
499CommunicationKDP::GetKernelVersion ()
500{
501 if (m_kernel_version.empty())
502 SendRequestKernelVersion ();
503 return m_kernel_version.c_str();
504}
505
506bool
507CommunicationKDP::SendRequestKernelVersion ()
508{
509 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000510 const CommandType command = KDP_KERNELVERSION;
Greg Clayton234981a2011-07-20 03:41:06 +0000511 const uint32_t command_length = 8;
512 const uint32_t request_sequence_id = m_request_sequence_id;
513 MakeRequestPacketHeader (command, request_packet, command_length);
514 DataExtractor reply_packet;
515 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
516 {
517 const char *kernel_version_cstr = reply_packet.PeekCStr(8);
518 if (kernel_version_cstr && kernel_version_cstr[0])
519 m_kernel_version.assign (kernel_version_cstr);
520 return true;
521 }
522 return false;
523}
524
Greg Claytond52d00f2011-07-16 03:19:08 +0000525bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000526CommunicationKDP::SendRequestDisconnect ()
Greg Clayton1e5b0212011-07-15 16:31:38 +0000527{
Greg Clayton0fa51242011-07-19 03:57:15 +0000528 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000529 const CommandType command = KDP_DISCONNECT;
Greg Claytond52d00f2011-07-16 03:19:08 +0000530 const uint32_t command_length = 8;
531 const uint32_t request_sequence_id = m_request_sequence_id;
532 MakeRequestPacketHeader (command, request_packet, command_length);
533 DataExtractor reply_packet;
534 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
535 {
536 // Are we supposed to get a reply for disconnect?
537 }
538 ClearKDPSettings ();
539 return true;
Greg Clayton1e5b0212011-07-15 16:31:38 +0000540}
541
Greg Clayton0fa51242011-07-19 03:57:15 +0000542uint32_t
543CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr,
544 void *dst,
545 uint32_t dst_len,
546 Error &error)
547{
548 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
549 bool use_64 = (GetVersion() >= 11);
550 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +0000551 const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM;
Greg Clayton0fa51242011-07-19 03:57:15 +0000552 // Size is header + address size + uint32_t length
553 const uint32_t command_length = 8 + command_addr_byte_size + 4;
554 const uint32_t request_sequence_id = m_request_sequence_id;
555 MakeRequestPacketHeader (command, request_packet, command_length);
556 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
557 request_packet.PutHex32 (dst_len);
558 DataExtractor reply_packet;
559 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
560 {
Greg Clayton0fa51242011-07-19 03:57:15 +0000561 uint32_t offset = 8;
562 uint32_t kdp_error = reply_packet.GetU32 (&offset);
563 uint32_t src_len = reply_packet.GetByteSize() - 12;
564
565 if (src_len > 0)
566 {
567 const void *src = reply_packet.GetData(&offset, src_len);
568 if (src)
569 {
570 ::memcpy (dst, src, src_len);
571 error.Clear();
572 return src_len;
573 }
574 }
575 if (kdp_error)
576 error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error);
577 else
578 error.SetErrorString ("kdp read memory failed");
579 }
580 return 0;
581}
582
Greg Claytonec15f502011-07-20 01:32:50 +0000583
584uint32_t
585CommunicationKDP::SendRequestWriteMemory (lldb::addr_t addr,
586 const void *src,
587 uint32_t src_len,
588 Error &error)
589{
590 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
591 bool use_64 = (GetVersion() >= 11);
592 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +0000593 const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM;
Greg Claytonec15f502011-07-20 01:32:50 +0000594 // Size is header + address size + uint32_t length
595 const uint32_t command_length = 8 + command_addr_byte_size + 4;
596 const uint32_t request_sequence_id = m_request_sequence_id;
597 MakeRequestPacketHeader (command, request_packet, command_length);
598 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
599 request_packet.PutHex32 (src_len);
600 request_packet.PutBytesAsRawHex8(src, src_len);
601
602 DataExtractor reply_packet;
603 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
604 {
605 uint32_t offset = 8;
606 uint32_t kdp_error = reply_packet.GetU32 (&offset);
607 if (kdp_error)
608 error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error);
609 else
610 {
611 error.Clear();
612 return src_len;
613 }
614 }
615 return 0;
616}
617
Greg Clayton0fa51242011-07-19 03:57:15 +0000618const char *
619CommunicationKDP::GetCommandAsCString (uint8_t command)
620{
621 switch (command)
622 {
Greg Clayton7b139222011-07-21 01:12:01 +0000623 case KDP_CONNECT: return "KDP_CONNECT";
624 case KDP_DISCONNECT: return "KDP_DISCONNECT";
625 case KDP_HOSTINFO: return "KDP_HOSTINFO";
626 case KDP_VERSION: return "KDP_VERSION";
627 case KDP_MAXBYTES: return "KDP_MAXBYTES";
628 case KDP_READMEM: return "KDP_READMEM";
629 case KDP_WRITEMEM: return "KDP_WRITEMEM";
630 case KDP_READREGS: return "KDP_READREGS";
631 case KDP_WRITEREGS: return "KDP_WRITEREGS";
632 case KDP_LOAD: return "KDP_LOAD";
633 case KDP_IMAGEPATH: return "KDP_IMAGEPATH";
634 case KDP_SUSPEND: return "KDP_SUSPEND";
635 case KDP_RESUMECPUS: return "KDP_RESUMECPUS";
636 case KDP_EXCEPTION: return "KDP_EXCEPTION";
637 case KDP_TERMINATION: return "KDP_TERMINATION";
638 case KDP_BREAKPOINT_SET: return "KDP_BREAKPOINT_SET";
639 case KDP_BREAKPOINT_REMOVE: return "KDP_BREAKPOINT_REMOVE";
640 case KDP_REGIONS: return "KDP_REGIONS";
641 case KDP_REATTACH: return "KDP_REATTACH";
642 case KDP_HOSTREBOOT: return "KDP_HOSTREBOOT";
643 case KDP_READMEM64: return "KDP_READMEM64";
644 case KDP_WRITEMEM64: return "KDP_WRITEMEM64";
645 case KDP_BREAKPOINT_SET64: return "KDP_BREAKPOINT64_SET";
646 case KDP_BREAKPOINT_REMOVE64: return "KDP_BREAKPOINT64_REMOVE";
647 case KDP_KERNELVERSION: return "KDP_KERNELVERSION";
Greg Clayton0fa51242011-07-19 03:57:15 +0000648 }
649 return NULL;
650}
651
652void
653CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len)
654{
655 DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size);
656 DumpPacket (s, extractor);
657}
658
659void
660CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
661{
662 const char *error_desc = NULL;
663 if (packet.GetByteSize() < 8)
664 {
665 error_desc = "error: invalid packet (too short): ";
666 }
667 else
668 {
669 uint32_t offset = 0;
670 const uint8_t first_packet_byte = packet.GetU8 (&offset);
671 const uint8_t sequence_id = packet.GetU8 (&offset);
672 const uint16_t length = packet.GetU16 (&offset);
673 const uint32_t key = packet.GetU32 (&offset);
674 const CommandType command = ExtractCommand (first_packet_byte);
675 const char *command_name = GetCommandAsCString (command);
676 if (command_name)
677 {
678 const bool is_reply = ExtractIsReply(first_packet_byte);
679 s.Printf ("%s {%u:%u} <0x%4.4x> %s",
680 is_reply ? "<--" : "-->",
681 key,
682 sequence_id,
683 length,
684 command_name);
685
686 if (is_reply)
687 {
688 // Dump request reply packets
689 switch (command)
690 {
Greg Claytonec15f502011-07-20 01:32:50 +0000691 // Commands that return a single 32 bit error
Greg Clayton7b139222011-07-21 01:12:01 +0000692 case KDP_CONNECT:
693 case KDP_WRITEMEM:
694 case KDP_WRITEMEM64:
695 case KDP_BREAKPOINT_SET:
696 case KDP_BREAKPOINT_REMOVE:
697 case KDP_BREAKPOINT_SET64:
698 case KDP_BREAKPOINT_REMOVE64:
699 case KDP_WRITEREGS:
700 case KDP_LOAD:
Greg Clayton0fa51242011-07-19 03:57:15 +0000701 {
702 const uint32_t error = packet.GetU32 (&offset);
703 s.Printf(" (error=0x%8.8x)", error);
704 }
705 break;
706
Greg Clayton7b139222011-07-21 01:12:01 +0000707 case KDP_DISCONNECT:
708 case KDP_REATTACH:
709 case KDP_HOSTREBOOT:
710 case KDP_SUSPEND:
711 case KDP_RESUMECPUS:
712 case KDP_EXCEPTION:
713 case KDP_TERMINATION:
Greg Clayton0fa51242011-07-19 03:57:15 +0000714 // No return value for the reply, just the header to ack
Greg Claytonec15f502011-07-20 01:32:50 +0000715 s.PutCString(" ()");
Greg Clayton0fa51242011-07-19 03:57:15 +0000716 break;
717
Greg Clayton7b139222011-07-21 01:12:01 +0000718 case KDP_HOSTINFO:
Greg Clayton0fa51242011-07-19 03:57:15 +0000719 {
720 const uint32_t cpu_mask = packet.GetU32 (&offset);
721 const uint32_t cpu_type = packet.GetU32 (&offset);
722 const uint32_t cpu_subtype = packet.GetU32 (&offset);
723 s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype);
724 }
725 break;
726
Greg Clayton7b139222011-07-21 01:12:01 +0000727 case KDP_VERSION:
Greg Clayton0fa51242011-07-19 03:57:15 +0000728 {
729 const uint32_t version = packet.GetU32 (&offset);
730 const uint32_t feature = packet.GetU32 (&offset);
731 s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
732 }
733 break;
734
Greg Clayton7b139222011-07-21 01:12:01 +0000735 case KDP_REGIONS:
Greg Clayton0fa51242011-07-19 03:57:15 +0000736 {
737 const uint32_t region_count = packet.GetU32 (&offset);
738 s.Printf(" (count = %u", region_count);
739 for (uint32_t i=0; i<region_count; ++i)
740 {
741 const addr_t region_addr = packet.GetPointer (&offset);
742 const uint32_t region_size = packet.GetU32 (&offset);
743 const uint32_t region_prot = packet.GetU32 (&offset);
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000744 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 +0000745 }
746 }
747 break;
748
Greg Clayton7b139222011-07-21 01:12:01 +0000749 case KDP_READMEM:
750 case KDP_READMEM64:
Greg Clayton0fa51242011-07-19 03:57:15 +0000751 {
752 const uint32_t error = packet.GetU32 (&offset);
Greg Claytonec15f502011-07-20 01:32:50 +0000753 const uint32_t count = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000754 s.Printf(" (error = 0x%8.8x:\n", error);
Greg Clayton0fa51242011-07-19 03:57:15 +0000755 if (count > 0)
Greg Clayton234981a2011-07-20 03:41:06 +0000756 packet.Dump (&s, // Stream to dump to
757 offset, // Offset within "packet"
758 eFormatBytesWithASCII, // Format to use
759 1, // Size of each item in bytes
760 count, // Number of items
761 16, // Number per line
762 m_last_read_memory_addr, // Don't show addresses before each line
763 0, 0); // No bitfields
Greg Clayton0fa51242011-07-19 03:57:15 +0000764 }
765 break;
766
Greg Clayton7b139222011-07-21 01:12:01 +0000767 case KDP_READREGS:
Greg Claytonec15f502011-07-20 01:32:50 +0000768 {
769 const uint32_t error = packet.GetU32 (&offset);
770 const uint32_t count = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000771 s.Printf(" (error = 0x%8.8x regs:\n", error);
Greg Claytonec15f502011-07-20 01:32:50 +0000772 if (count > 0)
773 packet.Dump (&s, // Stream to dump to
774 offset, // Offset within "packet"
775 eFormatHex, // Format to use
776 m_addr_byte_size, // Size of each item in bytes
777 count / m_addr_byte_size, // Number of items
778 16 / m_addr_byte_size, // Number per line
779 LLDB_INVALID_ADDRESS, // Don't show addresses before each line
780 0, 0); // No bitfields
781 }
782 break;
783
Greg Clayton7b139222011-07-21 01:12:01 +0000784 case KDP_KERNELVERSION:
Greg Clayton234981a2011-07-20 03:41:06 +0000785 {
786 const char *kernel_version = packet.PeekCStr(8);
787 s.Printf(" (version = \"%s\")", kernel_version);
788 }
789 break;
790
Greg Clayton7b139222011-07-21 01:12:01 +0000791 case KDP_MAXBYTES:
Greg Clayton234981a2011-07-20 03:41:06 +0000792 {
793 const uint32_t max_bytes = packet.GetU32 (&offset);
794 s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes);
795 }
796 break;
Greg Clayton7b139222011-07-21 01:12:01 +0000797 case KDP_IMAGEPATH:
Greg Clayton234981a2011-07-20 03:41:06 +0000798 {
799 const char *path = packet.GetCStr(&offset);
800 s.Printf(" (path = \"%s\")", path);
801 }
802 break;
803 default:
Greg Claytonec15f502011-07-20 01:32:50 +0000804 s.Printf(" (add support for dumping this packet reply!!!");
Greg Clayton0fa51242011-07-19 03:57:15 +0000805 break;
806
807 }
808 }
809 else
810 {
811 // Dump request packets
812 switch (command)
813 {
Greg Clayton7b139222011-07-21 01:12:01 +0000814 case KDP_CONNECT:
Greg Clayton0fa51242011-07-19 03:57:15 +0000815 {
816 const uint16_t reply_port = packet.GetU16 (&offset);
817 const uint16_t exc_port = packet.GetU16 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000818 s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset));
Greg Clayton0fa51242011-07-19 03:57:15 +0000819 }
820 break;
821
Greg Clayton7b139222011-07-21 01:12:01 +0000822 case KDP_DISCONNECT:
823 case KDP_HOSTREBOOT:
824 case KDP_HOSTINFO:
825 case KDP_VERSION:
826 case KDP_REGIONS:
827 case KDP_KERNELVERSION:
828 case KDP_MAXBYTES:
829 case KDP_IMAGEPATH:
830 case KDP_SUSPEND:
Greg Clayton0fa51242011-07-19 03:57:15 +0000831 // No args, just the header in the request...
Greg Clayton234981a2011-07-20 03:41:06 +0000832 s.PutCString(" ()");
833 break;
834
Greg Clayton7b139222011-07-21 01:12:01 +0000835 case KDP_RESUMECPUS:
Greg Clayton234981a2011-07-20 03:41:06 +0000836 {
837 const uint32_t cpu_mask = packet.GetU32 (&offset);
838 s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask);
839 }
Greg Clayton0fa51242011-07-19 03:57:15 +0000840 break;
841
Greg Clayton7b139222011-07-21 01:12:01 +0000842 case KDP_READMEM:
Greg Clayton0fa51242011-07-19 03:57:15 +0000843 {
844 const uint32_t addr = packet.GetU32 (&offset);
845 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000846 s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size);
Greg Clayton234981a2011-07-20 03:41:06 +0000847 m_last_read_memory_addr = addr;
Greg Clayton0fa51242011-07-19 03:57:15 +0000848 }
849 break;
850
Greg Clayton7b139222011-07-21 01:12:01 +0000851 case KDP_WRITEMEM:
Greg Claytonec15f502011-07-20 01:32:50 +0000852 {
853 const uint32_t addr = packet.GetU32 (&offset);
854 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000855 s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size);
Greg Claytonec15f502011-07-20 01:32:50 +0000856 if (size > 0)
857 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
858 }
859 break;
860
Greg Clayton7b139222011-07-21 01:12:01 +0000861 case KDP_READMEM64:
Greg Clayton0fa51242011-07-19 03:57:15 +0000862 {
863 const uint64_t addr = packet.GetU64 (&offset);
864 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000865 s.Printf(" (addr = 0x%16.16llx, size = %u)", addr, size);
Greg Clayton234981a2011-07-20 03:41:06 +0000866 m_last_read_memory_addr = addr;
Greg Clayton0fa51242011-07-19 03:57:15 +0000867 }
868 break;
869
Greg Clayton7b139222011-07-21 01:12:01 +0000870 case KDP_WRITEMEM64:
Greg Claytonec15f502011-07-20 01:32:50 +0000871 {
872 const uint64_t addr = packet.GetU64 (&offset);
873 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000874 s.Printf(" (addr = 0x%16.16llx, size = %u, bytes = \n", addr, size);
Greg Claytonec15f502011-07-20 01:32:50 +0000875 if (size > 0)
876 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
877 }
878 break;
879
Greg Clayton7b139222011-07-21 01:12:01 +0000880 case KDP_READREGS:
Greg Clayton0fa51242011-07-19 03:57:15 +0000881 {
882 const uint32_t cpu = packet.GetU32 (&offset);
883 const uint32_t flavor = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000884 s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor);
Greg Clayton0fa51242011-07-19 03:57:15 +0000885 }
886 break;
887
Greg Clayton7b139222011-07-21 01:12:01 +0000888 case KDP_WRITEREGS:
Greg Claytonec15f502011-07-20 01:32:50 +0000889 {
890 const uint32_t cpu = packet.GetU32 (&offset);
891 const uint32_t flavor = packet.GetU32 (&offset);
892 const uint32_t nbytes = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000893 s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor);
Greg Claytonec15f502011-07-20 01:32:50 +0000894 if (nbytes > 0)
895 packet.Dump (&s, // Stream to dump to
896 offset, // Offset within "packet"
897 eFormatHex, // Format to use
898 m_addr_byte_size, // Size of each item in bytes
899 nbytes / m_addr_byte_size, // Number of items
900 16 / m_addr_byte_size, // Number per line
901 LLDB_INVALID_ADDRESS, // Don't show addresses before each line
902 0, 0); // No bitfields
903 }
904 break;
905
Greg Claytonec15f502011-07-20 01:32:50 +0000906
Greg Clayton7b139222011-07-21 01:12:01 +0000907 case KDP_BREAKPOINT_SET:
908 case KDP_BREAKPOINT_REMOVE:
Greg Clayton234981a2011-07-20 03:41:06 +0000909 {
910 const uint32_t addr = packet.GetU32 (&offset);
911 s.Printf(" (addr = 0x%8.8x)", addr);
912 }
913 break;
914
Greg Clayton7b139222011-07-21 01:12:01 +0000915 case KDP_BREAKPOINT_SET64:
916 case KDP_BREAKPOINT_REMOVE64:
Greg Clayton234981a2011-07-20 03:41:06 +0000917 {
918 const uint64_t addr = packet.GetU64 (&offset);
919 s.Printf(" (addr = 0x%16.16llx)", addr);
920 }
921 break;
922
923
Greg Clayton7b139222011-07-21 01:12:01 +0000924 case KDP_LOAD:
Greg Clayton234981a2011-07-20 03:41:06 +0000925 {
926 const char *path = packet.GetCStr(&offset);
927 s.Printf(" (path = \"%s\")", path);
928 }
929 break;
930
Greg Clayton7b139222011-07-21 01:12:01 +0000931 case KDP_EXCEPTION:
Greg Clayton234981a2011-07-20 03:41:06 +0000932 {
933 const uint32_t count = packet.GetU32 (&offset);
934
935 s.Printf(" (count = %u:", count);
936 for (uint32_t i=0; i<count; ++i)
937 {
938 const uint32_t cpu = packet.GetU32 (&offset);
939 const uint32_t exc = packet.GetU32 (&offset);
940 const uint32_t code = packet.GetU32 (&offset);
941 const uint32_t subcode = packet.GetU32 (&offset);
942 const char *exc_cstr = NULL;
943 switch (exc)
944 {
945 case 1: exc_cstr = "EXC_BAD_ACCESS"; break;
946 case 2: exc_cstr = "EXC_BAD_INSTRUCTION"; break;
947 case 3: exc_cstr = "EXC_ARITHMETIC"; break;
948 case 4: exc_cstr = "EXC_EMULATION"; break;
949 case 5: exc_cstr = "EXC_SOFTWARE"; break;
950 case 6: exc_cstr = "EXC_BREAKPOINT"; break;
951 case 7: exc_cstr = "EXC_SYSCALL"; break;
952 case 8: exc_cstr = "EXC_MACH_SYSCALL"; break;
953 case 9: exc_cstr = "EXC_RPC_ALERT"; break;
954 case 10: exc_cstr = "EXC_CRASH"; break;
955 default:
956 break;
957 }
958
959 s.Printf ("\n cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)\n",
960 cpu, exc_cstr, exc, code, code, subcode, subcode);
961 }
962 }
963 break;
964
Greg Clayton7b139222011-07-21 01:12:01 +0000965 case KDP_TERMINATION:
Greg Clayton234981a2011-07-20 03:41:06 +0000966 {
967 const uint32_t term_code = packet.GetU32 (&offset);
968 const uint32_t exit_code = packet.GetU32 (&offset);
969 s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code);
970 }
Greg Clayton0fa51242011-07-19 03:57:15 +0000971 break;
972
Greg Clayton7b139222011-07-21 01:12:01 +0000973 case KDP_REATTACH:
Greg Clayton0fa51242011-07-19 03:57:15 +0000974 {
975 const uint16_t reply_port = packet.GetU16 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000976 s.Printf(" (reply_port = %u)", reply_port);
Greg Clayton0fa51242011-07-19 03:57:15 +0000977 }
978 break;
Greg Clayton0fa51242011-07-19 03:57:15 +0000979 }
980 }
981 }
982 else
983 {
984 error_desc = "error: invalid packet command: ";
985 }
986 }
987
988 if (error_desc)
989 {
990 s.PutCString (error_desc);
991
992 packet.Dump (&s, // Stream to dump to
993 0, // Offset into "packet"
994 eFormatBytes, // Dump as hex bytes
995 1, // Size of each item is 1 for single bytes
996 packet.GetByteSize(), // Number of bytes
997 UINT32_MAX, // Num bytes per line
998 LLDB_INVALID_ADDRESS, // Base address
999 0, 0); // Bitfield info set to not do anything bitfield related
1000 }
1001}
1002
1003uint32_t
1004CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
1005 uint32_t flavor,
1006 void *dst,
1007 uint32_t dst_len,
1008 Error &error)
1009{
1010 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001011 const CommandType command = KDP_READREGS;
Greg Clayton0fa51242011-07-19 03:57:15 +00001012 // Size is header + 4 byte cpu and 4 byte flavor
1013 const uint32_t command_length = 8 + 4 + 4;
1014 const uint32_t request_sequence_id = m_request_sequence_id;
1015 MakeRequestPacketHeader (command, request_packet, command_length);
1016 request_packet.PutHex32 (cpu);
1017 request_packet.PutHex32 (flavor);
1018 DataExtractor reply_packet;
1019 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1020 {
Greg Clayton0fa51242011-07-19 03:57:15 +00001021 uint32_t offset = 8;
1022 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1023 uint32_t src_len = reply_packet.GetByteSize() - 12;
1024
1025 if (src_len > 0)
1026 {
1027 const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
1028 const void *src = reply_packet.GetData(&offset, bytes_to_copy);
1029 if (src)
1030 {
1031 ::memcpy (dst, src, bytes_to_copy);
1032 error.Clear();
1033 // Return the number of bytes we could have returned regardless if
1034 // we copied them or not, just so we know when things don't match up
1035 return src_len;
1036 }
1037 }
1038 if (kdp_error)
1039 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
1040 else
1041 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
1042 }
1043 return 0;
1044}
1045
Greg Clayton234981a2011-07-20 03:41:06 +00001046
1047bool
1048CommunicationKDP::SendRequestResume (uint32_t cpu_mask)
1049{
1050 if (cpu_mask == 0)
1051 cpu_mask = GetCPUMask();
1052 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001053 const CommandType command = KDP_RESUMECPUS;
Greg Clayton234981a2011-07-20 03:41:06 +00001054 const uint32_t command_length = 12;
1055 const uint32_t request_sequence_id = m_request_sequence_id;
1056 MakeRequestPacketHeader (command, request_packet, command_length);
1057 request_packet.PutHex32(cpu_mask);
1058
1059 DataExtractor reply_packet;
1060 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1061 return true;
1062 return false;
1063}
1064
1065bool
1066CommunicationKDP::SendRequestBreakpoint (bool set, addr_t addr)
1067{
1068 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1069 bool use_64 = (GetVersion() >= 11);
1070 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +00001071 const CommandType command = set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET ):
1072 (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE);
Greg Clayton234981a2011-07-20 03:41:06 +00001073
1074 const uint32_t command_length = 8 + command_addr_byte_size;
1075 const uint32_t request_sequence_id = m_request_sequence_id;
1076 MakeRequestPacketHeader (command, request_packet, command_length);
1077 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
1078
1079 DataExtractor reply_packet;
1080 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
Greg Clayton1bc04ed2011-07-29 22:26:36 +00001081 {
1082 uint32_t offset = 8;
1083 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1084 if (kdp_error == 0)
1085 return true;
1086 }
Greg Clayton234981a2011-07-20 03:41:06 +00001087 return false;
1088}
1089
1090bool
1091CommunicationKDP::SendRequestSuspend ()
1092{
1093 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001094 const CommandType command = KDP_SUSPEND;
Greg Clayton234981a2011-07-20 03:41:06 +00001095 const uint32_t command_length = 8;
1096 const uint32_t request_sequence_id = m_request_sequence_id;
1097 MakeRequestPacketHeader (command, request_packet, command_length);
1098 DataExtractor reply_packet;
1099 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1100 return true;
1101 return false;
1102}
1103