blob: 39624dc978aa5a6e1cbf5bd3391d8fa0473b08c2 [file] [log] [blame]
Greg Clayton269f91e2011-07-15 18:02:58 +00001//===-- CommunicationKDP.cpp ------------------------------------*- C++ -*-===//
Greg Clayton363be3f2011-07-15 03:27:12 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10
11#include "CommunicationKDP.h"
12
13// C Includes
14#include <limits.h>
15#include <string.h>
16
17// C++ Includes
Greg Clayton0fa51242011-07-19 03:57:15 +000018#include "llvm/Support/MachO.h"
19
Greg Clayton363be3f2011-07-15 03:27:12 +000020// Other libraries and framework includes
Greg Claytond52d00f2011-07-16 03:19:08 +000021#include "lldb/Core/DataBufferHeap.h"
Greg Clayton1e5b0212011-07-15 16:31:38 +000022#include "lldb/Core/DataExtractor.h"
Greg Clayton363be3f2011-07-15 03:27:12 +000023#include "lldb/Core/Log.h"
Greg Clayton0fa51242011-07-19 03:57:15 +000024#include "lldb/Core/State.h"
Greg Clayton363be3f2011-07-15 03:27:12 +000025#include "lldb/Host/FileSpec.h"
26#include "lldb/Host/Host.h"
27#include "lldb/Host/TimeValue.h"
28#include "lldb/Target/Process.h"
Greg Clayton363be3f2011-07-15 03:27:12 +000029
30// Project includes
31#include "ProcessKDPLog.h"
32
33#define DEBUGSERVER_BASENAME "debugserver"
34
35using namespace lldb;
36using namespace lldb_private;
37
38//----------------------------------------------------------------------
39// CommunicationKDP constructor
40//----------------------------------------------------------------------
41CommunicationKDP::CommunicationKDP (const char *comm_name) :
42 Communication(comm_name),
Greg Clayton0fa51242011-07-19 03:57:15 +000043 m_addr_byte_size (4),
Greg Claytond52d00f2011-07-16 03:19:08 +000044 m_byte_order (eByteOrderLittle),
Greg Clayton363be3f2011-07-15 03:27:12 +000045 m_packet_timeout (1),
46 m_sequence_mutex (Mutex::eMutexTypeRecursive),
Greg Clayton363be3f2011-07-15 03:27:12 +000047 m_private_is_running (false),
Greg Claytond52d00f2011-07-16 03:19:08 +000048 m_session_key (0u),
49 m_request_sequence_id (0u),
50 m_exception_sequence_id (0u),
51 m_kdp_version_version (0u),
52 m_kdp_version_feature (0u),
53 m_kdp_hostinfo_cpu_mask (0u),
54 m_kdp_hostinfo_cpu_type (0u),
55 m_kdp_hostinfo_cpu_subtype (0u)
Greg Clayton363be3f2011-07-15 03:27:12 +000056{
57}
58
59//----------------------------------------------------------------------
60// Destructor
61//----------------------------------------------------------------------
62CommunicationKDP::~CommunicationKDP()
63{
64 if (IsConnected())
65 {
66 Disconnect();
67 }
68}
69
Greg Clayton1e5b0212011-07-15 16:31:38 +000070bool
Greg Claytond52d00f2011-07-16 03:19:08 +000071CommunicationKDP::SendRequestPacket (const PacketStreamType &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +000072{
73 Mutex::Locker locker(m_sequence_mutex);
Greg Clayton1e5b0212011-07-15 16:31:38 +000074 return SendRequestPacketNoLock (request_packet);
Greg Clayton363be3f2011-07-15 03:27:12 +000075}
76
Greg Claytond52d00f2011-07-16 03:19:08 +000077#if 0
78typedef struct {
79 uint8_t request; // Either: CommandType | ePacketTypeRequest, or CommandType | ePacketTypeReply
80 uint8_t sequence;
81 uint16_t length; // Length of entire packet including this header
82 uint32_t key; // Session key
83} kdp_hdr_t;
84#endif
85
Greg Clayton1e5b0212011-07-15 16:31:38 +000086void
Greg Claytond52d00f2011-07-16 03:19:08 +000087CommunicationKDP::MakeRequestPacketHeader (CommandType request_type,
88 PacketStreamType &request_packet,
89 uint16_t request_length)
Greg Clayton363be3f2011-07-15 03:27:12 +000090{
Greg Clayton1e5b0212011-07-15 16:31:38 +000091 request_packet.Clear();
Greg Claytond52d00f2011-07-16 03:19:08 +000092 request_packet.PutHex8 (request_type | ePacketTypeRequest); // Set the request type
93 request_packet.PutHex8 (m_request_sequence_id++); // Sequence number
94 request_packet.PutHex16 (request_length); // Length of the packet including this header
95 request_packet.PutHex32 (m_session_key); // Session key
Greg Clayton363be3f2011-07-15 03:27:12 +000096}
97
Greg Claytond52d00f2011-07-16 03:19:08 +000098bool
99CommunicationKDP::SendRequestAndGetReply (const CommandType command,
100 const uint8_t request_sequence_id,
101 const PacketStreamType &request_packet,
102 DataExtractor &reply_packet)
103{
104
105 Mutex::Locker locker(m_sequence_mutex);
106 if (SendRequestPacketNoLock(request_packet))
107 {
Greg Clayton8d2ea282011-07-17 20:36:25 +0000108 if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
Greg Claytond52d00f2011-07-16 03:19:08 +0000109 {
110 uint32_t offset = 0;
111 const uint8_t reply_command = reply_packet.GetU8 (&offset);
112 const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
113 if ((reply_command & eCommandTypeMask) == command)
114 {
115 if (request_sequence_id == reply_sequence_id)
116 return true;
117 }
118 }
119 }
120 reply_packet.Clear();
121 return false;
122}
Greg Clayton363be3f2011-07-15 03:27:12 +0000123
Greg Clayton1e5b0212011-07-15 16:31:38 +0000124bool
Greg Claytond52d00f2011-07-16 03:19:08 +0000125CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +0000126{
127 if (IsConnected())
128 {
Greg Clayton1e5b0212011-07-15 16:31:38 +0000129 const char *packet_data = request_packet.GetData();
130 const size_t packet_size = request_packet.GetSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000131
132 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
133 if (log)
Greg Clayton1e5b0212011-07-15 16:31:38 +0000134 {
Greg Clayton0fa51242011-07-19 03:57:15 +0000135 PacketStreamType log_strm;
136 DumpPacket (log_strm, packet_data, packet_size);
137 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton1e5b0212011-07-15 16:31:38 +0000138 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000139 ConnectionStatus status = eConnectionStatusSuccess;
Greg Clayton363be3f2011-07-15 03:27:12 +0000140
Greg Clayton1e5b0212011-07-15 16:31:38 +0000141 size_t bytes_written = Write (packet_data,
142 packet_size,
143 status,
144 NULL);
145
146 if (bytes_written == packet_size)
147 return true;
148
149 if (log)
150 log->Printf ("error: failed to send packet entire packet %zu of %zu bytes sent", bytes_written, packet_size);
151 }
152 return false;
Greg Clayton363be3f2011-07-15 03:27:12 +0000153}
154
155bool
156CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker)
157{
158 return locker.TryLock (m_sequence_mutex.GetMutex());
159}
160
161
162bool
163CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
164{
165 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
166}
167
168size_t
Greg Claytond52d00f2011-07-16 03:19:08 +0000169CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &packet, uint32_t timeout_usec)
Greg Clayton363be3f2011-07-15 03:27:12 +0000170{
171 Mutex::Locker locker(m_sequence_mutex);
172 return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
173}
174
175size_t
Greg Claytond52d00f2011-07-16 03:19:08 +0000176CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec)
Greg Clayton363be3f2011-07-15 03:27:12 +0000177{
178 uint8_t buffer[8192];
179 Error error;
180
181 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
182
183 // Check for a packet from our cache first without trying any reading...
184 if (CheckForPacket (NULL, 0, packet))
Greg Claytond52d00f2011-07-16 03:19:08 +0000185 return packet.GetByteSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000186
187 bool timed_out = false;
188 while (IsConnected() && !timed_out)
189 {
Johnny Chen1e3a5222011-07-21 19:00:59 +0000190 lldb::ConnectionStatus status = eConnectionStatusNoConnection;
Greg Clayton363be3f2011-07-15 03:27:12 +0000191 size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
192
193 if (log)
194 log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu",
195 __PRETTY_FUNCTION__,
196 timeout_usec,
197 Communication::ConnectionStatusAsCString (status),
198 error.AsCString(),
199 bytes_read);
200
201 if (bytes_read > 0)
202 {
203 if (CheckForPacket (buffer, bytes_read, packet))
Greg Claytond52d00f2011-07-16 03:19:08 +0000204 return packet.GetByteSize();
Greg Clayton363be3f2011-07-15 03:27:12 +0000205 }
206 else
207 {
208 switch (status)
209 {
210 case eConnectionStatusTimedOut:
211 timed_out = true;
212 break;
213 case eConnectionStatusSuccess:
214 //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
215 break;
216
217 case eConnectionStatusEndOfFile:
218 case eConnectionStatusNoConnection:
219 case eConnectionStatusLostConnection:
220 case eConnectionStatusError:
221 Disconnect();
222 break;
223 }
224 }
225 }
226 packet.Clear ();
227 return 0;
228}
229
230bool
Greg Claytond52d00f2011-07-16 03:19:08 +0000231CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet)
Greg Clayton363be3f2011-07-15 03:27:12 +0000232{
233 // Put the packet data into the buffer in a thread safe fashion
234 Mutex::Locker locker(m_bytes_mutex);
235
236 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
237
238 if (src && src_len > 0)
239 {
240 if (log && log->GetVerbose())
241 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000242 PacketStreamType log_strm;
Greg Clayton8d2ea282011-07-17 20:36:25 +0000243 DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS);
Greg Claytond52d00f2011-07-16 03:19:08 +0000244 log->Printf ("CommunicationKDP::%s adding %u bytes: %s",
Greg Clayton363be3f2011-07-15 03:27:12 +0000245 __FUNCTION__,
246 (uint32_t)src_len,
Greg Claytond52d00f2011-07-16 03:19:08 +0000247 log_strm.GetData());
Greg Clayton363be3f2011-07-15 03:27:12 +0000248 }
249 m_bytes.append ((const char *)src, src_len);
250 }
251
Greg Claytond52d00f2011-07-16 03:19:08 +0000252 // Make sure we at least have enough bytes for a packet header
253 const size_t bytes_available = m_bytes.size();
254 if (bytes_available >= 8)
Greg Clayton363be3f2011-07-15 03:27:12 +0000255 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000256 packet.SetData (&m_bytes[0], bytes_available, m_byte_order);
257 uint32_t offset = 0;
258 uint8_t reply_command = packet.GetU8(&offset);
259 switch (reply_command)
260 {
Greg Clayton7b139222011-07-21 01:12:01 +0000261 case ePacketTypeReply | KDP_CONNECT:
262 case ePacketTypeReply | KDP_DISCONNECT:
263 case ePacketTypeReply | KDP_HOSTINFO:
264 case ePacketTypeReply | KDP_VERSION:
265 case ePacketTypeReply | KDP_MAXBYTES:
266 case ePacketTypeReply | KDP_READMEM:
267 case ePacketTypeReply | KDP_WRITEMEM:
268 case ePacketTypeReply | KDP_READREGS:
269 case ePacketTypeReply | KDP_WRITEREGS:
270 case ePacketTypeReply | KDP_LOAD:
271 case ePacketTypeReply | KDP_IMAGEPATH:
272 case ePacketTypeReply | KDP_SUSPEND:
273 case ePacketTypeReply | KDP_RESUMECPUS:
274 case ePacketTypeReply | KDP_EXCEPTION:
275 case ePacketTypeReply | KDP_TERMINATION:
276 case ePacketTypeReply | KDP_BREAKPOINT_SET:
277 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE:
278 case ePacketTypeReply | KDP_REGIONS:
279 case ePacketTypeReply | KDP_REATTACH:
280 case ePacketTypeReply | KDP_HOSTREBOOT:
281 case ePacketTypeReply | KDP_READMEM64:
282 case ePacketTypeReply | KDP_WRITEMEM64:
283 case ePacketTypeReply | KDP_BREAKPOINT_SET64:
284 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64:
285 case ePacketTypeReply | KDP_KERNELVERSION:
Greg Claytond52d00f2011-07-16 03:19:08 +0000286 {
287 offset = 2;
288 const uint16_t length = packet.GetU16 (&offset);
289 if (length <= bytes_available)
290 {
291 // We have an entire packet ready, we need to copy the data
292 // bytes into a buffer that will be owned by the packet and
293 // erase the bytes from our communcation buffer "m_bytes"
294 packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length)));
295 m_bytes.erase (0, length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000296
297 if (log)
298 {
299 PacketStreamType log_strm;
Greg Clayton0fa51242011-07-19 03:57:15 +0000300 DumpPacket (log_strm, packet);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000301
Greg Clayton0fa51242011-07-19 03:57:15 +0000302 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton8d2ea282011-07-17 20:36:25 +0000303 }
Greg Claytond52d00f2011-07-16 03:19:08 +0000304 return true;
305 }
306 }
307 break;
308
309 default:
310 // Unrecognized reply command byte, erase this byte and try to get back on track
311 if (log)
312 log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
313 __FUNCTION__,
314 (uint8_t)m_bytes[0]);
315 m_bytes.erase(0, 1);
316 break;
317 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000318 }
319 packet.Clear();
320 return false;
321}
322
Greg Clayton1e5b0212011-07-15 16:31:38 +0000323
Greg Claytond52d00f2011-07-16 03:19:08 +0000324bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000325CommunicationKDP::SendRequestConnect (uint16_t reply_port,
326 uint16_t exc_port,
327 const char *greeting)
Greg Clayton1e5b0212011-07-15 16:31:38 +0000328{
Greg Clayton0fa51242011-07-19 03:57:15 +0000329 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000330 if (greeting == NULL)
331 greeting = "";
332
Greg Clayton7b139222011-07-21 01:12:01 +0000333 const CommandType command = KDP_CONNECT;
Greg Clayton8d2ea282011-07-17 20:36:25 +0000334 // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL
335 const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
Greg Claytond52d00f2011-07-16 03:19:08 +0000336 const uint32_t request_sequence_id = m_request_sequence_id;
337 MakeRequestPacketHeader (command, request_packet, command_length);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000338 // Always send connect ports as little endian
339 request_packet.SetByteOrder (eByteOrderLittle);
340 request_packet.PutHex16 (reply_port);
341 request_packet.PutHex16 (exc_port);
342 request_packet.SetByteOrder (m_byte_order);
343 request_packet.PutCString (greeting);
Greg Claytond52d00f2011-07-16 03:19:08 +0000344 DataExtractor reply_packet;
345 return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
Greg Clayton1e5b0212011-07-15 16:31:38 +0000346}
347
Greg Claytond52d00f2011-07-16 03:19:08 +0000348void
349CommunicationKDP::ClearKDPSettings ()
350{
351 m_request_sequence_id = 0;
352 m_kdp_version_version = 0;
353 m_kdp_version_feature = 0;
354 m_kdp_hostinfo_cpu_mask = 0;
355 m_kdp_hostinfo_cpu_type = 0;
356 m_kdp_hostinfo_cpu_subtype = 0;
357}
358
359bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000360CommunicationKDP::SendRequestReattach (uint16_t reply_port)
Greg Claytond52d00f2011-07-16 03:19:08 +0000361{
Greg Clayton0fa51242011-07-19 03:57:15 +0000362 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000363 const CommandType command = KDP_REATTACH;
Greg Claytond52d00f2011-07-16 03:19:08 +0000364 // Length is 8 bytes for the header plus 2 bytes for the reply UDP port
365 const uint32_t command_length = 8 + 2;
366 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);
Greg Claytond52d00f2011-07-16 03:19:08 +0000370 request_packet.PutHex16(reply_port);
Greg Clayton8d2ea282011-07-17 20:36:25 +0000371 request_packet.SetByteOrder (m_byte_order);
Greg Claytond52d00f2011-07-16 03:19:08 +0000372 DataExtractor reply_packet;
373 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
374 {
375 // Reset the sequence ID to zero for reattach
376 ClearKDPSettings ();
377 uint32_t offset = 4;
378 m_session_key = reply_packet.GetU32 (&offset);
379 return true;
380 }
381 return false;
382}
383
384uint32_t
385CommunicationKDP::GetVersion ()
386{
387 if (!VersionIsValid())
388 SendRequestVersion();
389 return m_kdp_version_version;
390}
391
392uint32_t
393CommunicationKDP::GetFeatureFlags ()
394{
395 if (!VersionIsValid())
396 SendRequestVersion();
397 return m_kdp_version_feature;
398}
399
400bool
401CommunicationKDP::SendRequestVersion ()
402{
Greg Clayton0fa51242011-07-19 03:57:15 +0000403 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000404 const CommandType command = KDP_VERSION;
Greg Claytond52d00f2011-07-16 03:19:08 +0000405 const uint32_t command_length = 8;
406 const uint32_t request_sequence_id = m_request_sequence_id;
407 MakeRequestPacketHeader (command, request_packet, command_length);
408 DataExtractor reply_packet;
409 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
410 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000411 uint32_t offset = 8;
412 m_kdp_version_version = reply_packet.GetU32 (&offset);
413 m_kdp_version_feature = reply_packet.GetU32 (&offset);
414 return true;
415 }
416 return false;
417}
418
Greg Clayton7b139222011-07-21 01:12:01 +0000419#if 0 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...
420const char *
421CommunicationKDP::GetImagePath ()
422{
423 if (m_image_path.empty())
424 SendRequestImagePath();
425 return m_image_path.c_str();
426}
427
428bool
429CommunicationKDP::SendRequestImagePath ()
430{
431 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
432 const CommandType command = KDP_IMAGEPATH;
433 const uint32_t command_length = 8;
434 const uint32_t request_sequence_id = m_request_sequence_id;
435 MakeRequestPacketHeader (command, request_packet, command_length);
436 DataExtractor reply_packet;
437 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
438 {
439 const char *path = reply_packet.PeekCStr(8);
440 if (path && path[0])
441 m_kernel_version.assign (path);
442 return true;
443 }
444 return false;
445}
446#endif
447
Greg Claytond52d00f2011-07-16 03:19:08 +0000448uint32_t
449CommunicationKDP::GetCPUMask ()
450{
451 if (!HostInfoIsValid())
452 SendRequestHostInfo();
453 return m_kdp_hostinfo_cpu_mask;
454}
455
456uint32_t
457CommunicationKDP::GetCPUType ()
458{
459 if (!HostInfoIsValid())
460 SendRequestHostInfo();
461 return m_kdp_hostinfo_cpu_type;
462}
463
464uint32_t
465CommunicationKDP::GetCPUSubtype ()
466{
467 if (!HostInfoIsValid())
468 SendRequestHostInfo();
469 return m_kdp_hostinfo_cpu_subtype;
470}
471
472bool
473CommunicationKDP::SendRequestHostInfo ()
474{
Greg Clayton0fa51242011-07-19 03:57:15 +0000475 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000476 const CommandType command = KDP_HOSTINFO;
Greg Claytond52d00f2011-07-16 03:19:08 +0000477 const uint32_t command_length = 8;
478 const uint32_t request_sequence_id = m_request_sequence_id;
479 MakeRequestPacketHeader (command, request_packet, command_length);
480 DataExtractor reply_packet;
481 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
482 {
Greg Claytond52d00f2011-07-16 03:19:08 +0000483 uint32_t offset = 8;
Greg Clayton0fa51242011-07-19 03:57:15 +0000484 m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
485 m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
486 m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
487
488 ArchSpec kernel_arch;
489 kernel_arch.SetArchitecture (eArchTypeMachO,
490 m_kdp_hostinfo_cpu_type,
491 m_kdp_hostinfo_cpu_subtype);
492
493 m_addr_byte_size = kernel_arch.GetAddressByteSize();
494 m_byte_order = kernel_arch.GetByteOrder();
Greg Claytond52d00f2011-07-16 03:19:08 +0000495 return true;
496 }
497 return false;
498}
499
Greg Clayton234981a2011-07-20 03:41:06 +0000500const char *
501CommunicationKDP::GetKernelVersion ()
502{
503 if (m_kernel_version.empty())
504 SendRequestKernelVersion ();
505 return m_kernel_version.c_str();
506}
507
508bool
509CommunicationKDP::SendRequestKernelVersion ()
510{
511 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000512 const CommandType command = KDP_KERNELVERSION;
Greg Clayton234981a2011-07-20 03:41:06 +0000513 const uint32_t command_length = 8;
514 const uint32_t request_sequence_id = m_request_sequence_id;
515 MakeRequestPacketHeader (command, request_packet, command_length);
516 DataExtractor reply_packet;
517 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
518 {
519 const char *kernel_version_cstr = reply_packet.PeekCStr(8);
520 if (kernel_version_cstr && kernel_version_cstr[0])
521 m_kernel_version.assign (kernel_version_cstr);
522 return true;
523 }
524 return false;
525}
526
Greg Claytond52d00f2011-07-16 03:19:08 +0000527bool
Greg Clayton8d2ea282011-07-17 20:36:25 +0000528CommunicationKDP::SendRequestDisconnect ()
Greg Clayton1e5b0212011-07-15 16:31:38 +0000529{
Greg Clayton0fa51242011-07-19 03:57:15 +0000530 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +0000531 const CommandType command = KDP_DISCONNECT;
Greg Claytond52d00f2011-07-16 03:19:08 +0000532 const uint32_t command_length = 8;
533 const uint32_t request_sequence_id = m_request_sequence_id;
534 MakeRequestPacketHeader (command, request_packet, command_length);
535 DataExtractor reply_packet;
536 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
537 {
538 // Are we supposed to get a reply for disconnect?
539 }
540 ClearKDPSettings ();
541 return true;
Greg Clayton1e5b0212011-07-15 16:31:38 +0000542}
543
Greg Clayton0fa51242011-07-19 03:57:15 +0000544uint32_t
545CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr,
546 void *dst,
547 uint32_t dst_len,
548 Error &error)
549{
550 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
551 bool use_64 = (GetVersion() >= 11);
552 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +0000553 const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM;
Greg Clayton0fa51242011-07-19 03:57:15 +0000554 // Size is header + address size + uint32_t length
555 const uint32_t command_length = 8 + command_addr_byte_size + 4;
556 const uint32_t request_sequence_id = m_request_sequence_id;
557 MakeRequestPacketHeader (command, request_packet, command_length);
558 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
559 request_packet.PutHex32 (dst_len);
560 DataExtractor reply_packet;
561 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
562 {
Greg Clayton0fa51242011-07-19 03:57:15 +0000563 uint32_t offset = 8;
564 uint32_t kdp_error = reply_packet.GetU32 (&offset);
565 uint32_t src_len = reply_packet.GetByteSize() - 12;
566
567 if (src_len > 0)
568 {
569 const void *src = reply_packet.GetData(&offset, src_len);
570 if (src)
571 {
572 ::memcpy (dst, src, src_len);
573 error.Clear();
574 return src_len;
575 }
576 }
577 if (kdp_error)
578 error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error);
579 else
580 error.SetErrorString ("kdp read memory failed");
581 }
582 return 0;
583}
584
Greg Claytonec15f502011-07-20 01:32:50 +0000585
586uint32_t
587CommunicationKDP::SendRequestWriteMemory (lldb::addr_t addr,
588 const void *src,
589 uint32_t src_len,
590 Error &error)
591{
592 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
593 bool use_64 = (GetVersion() >= 11);
594 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +0000595 const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM;
Greg Claytonec15f502011-07-20 01:32:50 +0000596 // Size is header + address size + uint32_t length
597 const uint32_t command_length = 8 + command_addr_byte_size + 4;
598 const uint32_t request_sequence_id = m_request_sequence_id;
599 MakeRequestPacketHeader (command, request_packet, command_length);
600 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
601 request_packet.PutHex32 (src_len);
602 request_packet.PutBytesAsRawHex8(src, src_len);
603
604 DataExtractor reply_packet;
605 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
606 {
607 uint32_t offset = 8;
608 uint32_t kdp_error = reply_packet.GetU32 (&offset);
609 if (kdp_error)
610 error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error);
611 else
612 {
613 error.Clear();
614 return src_len;
615 }
616 }
617 return 0;
618}
619
Greg Clayton0fa51242011-07-19 03:57:15 +0000620const char *
621CommunicationKDP::GetCommandAsCString (uint8_t command)
622{
623 switch (command)
624 {
Greg Clayton7b139222011-07-21 01:12:01 +0000625 case KDP_CONNECT: return "KDP_CONNECT";
626 case KDP_DISCONNECT: return "KDP_DISCONNECT";
627 case KDP_HOSTINFO: return "KDP_HOSTINFO";
628 case KDP_VERSION: return "KDP_VERSION";
629 case KDP_MAXBYTES: return "KDP_MAXBYTES";
630 case KDP_READMEM: return "KDP_READMEM";
631 case KDP_WRITEMEM: return "KDP_WRITEMEM";
632 case KDP_READREGS: return "KDP_READREGS";
633 case KDP_WRITEREGS: return "KDP_WRITEREGS";
634 case KDP_LOAD: return "KDP_LOAD";
635 case KDP_IMAGEPATH: return "KDP_IMAGEPATH";
636 case KDP_SUSPEND: return "KDP_SUSPEND";
637 case KDP_RESUMECPUS: return "KDP_RESUMECPUS";
638 case KDP_EXCEPTION: return "KDP_EXCEPTION";
639 case KDP_TERMINATION: return "KDP_TERMINATION";
640 case KDP_BREAKPOINT_SET: return "KDP_BREAKPOINT_SET";
641 case KDP_BREAKPOINT_REMOVE: return "KDP_BREAKPOINT_REMOVE";
642 case KDP_REGIONS: return "KDP_REGIONS";
643 case KDP_REATTACH: return "KDP_REATTACH";
644 case KDP_HOSTREBOOT: return "KDP_HOSTREBOOT";
645 case KDP_READMEM64: return "KDP_READMEM64";
646 case KDP_WRITEMEM64: return "KDP_WRITEMEM64";
647 case KDP_BREAKPOINT_SET64: return "KDP_BREAKPOINT64_SET";
648 case KDP_BREAKPOINT_REMOVE64: return "KDP_BREAKPOINT64_REMOVE";
649 case KDP_KERNELVERSION: return "KDP_KERNELVERSION";
Greg Clayton0fa51242011-07-19 03:57:15 +0000650 }
651 return NULL;
652}
653
654void
655CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len)
656{
657 DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size);
658 DumpPacket (s, extractor);
659}
660
661void
662CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet)
663{
664 const char *error_desc = NULL;
665 if (packet.GetByteSize() < 8)
666 {
667 error_desc = "error: invalid packet (too short): ";
668 }
669 else
670 {
671 uint32_t offset = 0;
672 const uint8_t first_packet_byte = packet.GetU8 (&offset);
673 const uint8_t sequence_id = packet.GetU8 (&offset);
674 const uint16_t length = packet.GetU16 (&offset);
675 const uint32_t key = packet.GetU32 (&offset);
676 const CommandType command = ExtractCommand (first_packet_byte);
677 const char *command_name = GetCommandAsCString (command);
678 if (command_name)
679 {
680 const bool is_reply = ExtractIsReply(first_packet_byte);
681 s.Printf ("%s {%u:%u} <0x%4.4x> %s",
682 is_reply ? "<--" : "-->",
683 key,
684 sequence_id,
685 length,
686 command_name);
687
688 if (is_reply)
689 {
690 // Dump request reply packets
691 switch (command)
692 {
Greg Claytonec15f502011-07-20 01:32:50 +0000693 // Commands that return a single 32 bit error
Greg Clayton7b139222011-07-21 01:12:01 +0000694 case KDP_CONNECT:
695 case KDP_WRITEMEM:
696 case KDP_WRITEMEM64:
697 case KDP_BREAKPOINT_SET:
698 case KDP_BREAKPOINT_REMOVE:
699 case KDP_BREAKPOINT_SET64:
700 case KDP_BREAKPOINT_REMOVE64:
701 case KDP_WRITEREGS:
702 case KDP_LOAD:
Greg Clayton0fa51242011-07-19 03:57:15 +0000703 {
704 const uint32_t error = packet.GetU32 (&offset);
705 s.Printf(" (error=0x%8.8x)", error);
706 }
707 break;
708
Greg Clayton7b139222011-07-21 01:12:01 +0000709 case KDP_DISCONNECT:
710 case KDP_REATTACH:
711 case KDP_HOSTREBOOT:
712 case KDP_SUSPEND:
713 case KDP_RESUMECPUS:
714 case KDP_EXCEPTION:
715 case KDP_TERMINATION:
Greg Clayton0fa51242011-07-19 03:57:15 +0000716 // No return value for the reply, just the header to ack
Greg Claytonec15f502011-07-20 01:32:50 +0000717 s.PutCString(" ()");
Greg Clayton0fa51242011-07-19 03:57:15 +0000718 break;
719
Greg Clayton7b139222011-07-21 01:12:01 +0000720 case KDP_HOSTINFO:
Greg Clayton0fa51242011-07-19 03:57:15 +0000721 {
722 const uint32_t cpu_mask = packet.GetU32 (&offset);
723 const uint32_t cpu_type = packet.GetU32 (&offset);
724 const uint32_t cpu_subtype = packet.GetU32 (&offset);
725 s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype);
726 }
727 break;
728
Greg Clayton7b139222011-07-21 01:12:01 +0000729 case KDP_VERSION:
Greg Clayton0fa51242011-07-19 03:57:15 +0000730 {
731 const uint32_t version = packet.GetU32 (&offset);
732 const uint32_t feature = packet.GetU32 (&offset);
733 s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
734 }
735 break;
736
Greg Clayton7b139222011-07-21 01:12:01 +0000737 case KDP_REGIONS:
Greg Clayton0fa51242011-07-19 03:57:15 +0000738 {
739 const uint32_t region_count = packet.GetU32 (&offset);
740 s.Printf(" (count = %u", region_count);
741 for (uint32_t i=0; i<region_count; ++i)
742 {
743 const addr_t region_addr = packet.GetPointer (&offset);
744 const uint32_t region_size = packet.GetU32 (&offset);
745 const uint32_t region_prot = packet.GetU32 (&offset);
746 s.Printf("\n\tregion[%i] = { range = [0x%16.16llx - 0x%16.16llx), size = 0x%8.8x, prot = %s }", region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot));
747 }
748 }
749 break;
750
Greg Clayton7b139222011-07-21 01:12:01 +0000751 case KDP_READMEM:
752 case KDP_READMEM64:
Greg Clayton0fa51242011-07-19 03:57:15 +0000753 {
754 const uint32_t error = packet.GetU32 (&offset);
Greg Claytonec15f502011-07-20 01:32:50 +0000755 const uint32_t count = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000756 s.Printf(" (error = 0x%8.8x:\n", error);
Greg Clayton0fa51242011-07-19 03:57:15 +0000757 if (count > 0)
Greg Clayton234981a2011-07-20 03:41:06 +0000758 packet.Dump (&s, // Stream to dump to
759 offset, // Offset within "packet"
760 eFormatBytesWithASCII, // Format to use
761 1, // Size of each item in bytes
762 count, // Number of items
763 16, // Number per line
764 m_last_read_memory_addr, // Don't show addresses before each line
765 0, 0); // No bitfields
Greg Clayton0fa51242011-07-19 03:57:15 +0000766 }
767 break;
768
Greg Clayton7b139222011-07-21 01:12:01 +0000769 case KDP_READREGS:
Greg Claytonec15f502011-07-20 01:32:50 +0000770 {
771 const uint32_t error = packet.GetU32 (&offset);
772 const uint32_t count = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000773 s.Printf(" (error = 0x%8.8x regs:\n", error);
Greg Claytonec15f502011-07-20 01:32:50 +0000774 if (count > 0)
775 packet.Dump (&s, // Stream to dump to
776 offset, // Offset within "packet"
777 eFormatHex, // Format to use
778 m_addr_byte_size, // Size of each item in bytes
779 count / m_addr_byte_size, // Number of items
780 16 / m_addr_byte_size, // Number per line
781 LLDB_INVALID_ADDRESS, // Don't show addresses before each line
782 0, 0); // No bitfields
783 }
784 break;
785
Greg Clayton7b139222011-07-21 01:12:01 +0000786 case KDP_KERNELVERSION:
Greg Clayton234981a2011-07-20 03:41:06 +0000787 {
788 const char *kernel_version = packet.PeekCStr(8);
789 s.Printf(" (version = \"%s\")", kernel_version);
790 }
791 break;
792
Greg Clayton7b139222011-07-21 01:12:01 +0000793 case KDP_MAXBYTES:
Greg Clayton234981a2011-07-20 03:41:06 +0000794 {
795 const uint32_t max_bytes = packet.GetU32 (&offset);
796 s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes);
797 }
798 break;
Greg Clayton7b139222011-07-21 01:12:01 +0000799 case KDP_IMAGEPATH:
Greg Clayton234981a2011-07-20 03:41:06 +0000800 {
801 const char *path = packet.GetCStr(&offset);
802 s.Printf(" (path = \"%s\")", path);
803 }
804 break;
805 default:
Greg Claytonec15f502011-07-20 01:32:50 +0000806 s.Printf(" (add support for dumping this packet reply!!!");
Greg Clayton0fa51242011-07-19 03:57:15 +0000807 break;
808
809 }
810 }
811 else
812 {
813 // Dump request packets
814 switch (command)
815 {
Greg Clayton7b139222011-07-21 01:12:01 +0000816 case KDP_CONNECT:
Greg Clayton0fa51242011-07-19 03:57:15 +0000817 {
818 const uint16_t reply_port = packet.GetU16 (&offset);
819 const uint16_t exc_port = packet.GetU16 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000820 s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset));
Greg Clayton0fa51242011-07-19 03:57:15 +0000821 }
822 break;
823
Greg Clayton7b139222011-07-21 01:12:01 +0000824 case KDP_DISCONNECT:
825 case KDP_HOSTREBOOT:
826 case KDP_HOSTINFO:
827 case KDP_VERSION:
828 case KDP_REGIONS:
829 case KDP_KERNELVERSION:
830 case KDP_MAXBYTES:
831 case KDP_IMAGEPATH:
832 case KDP_SUSPEND:
Greg Clayton0fa51242011-07-19 03:57:15 +0000833 // No args, just the header in the request...
Greg Clayton234981a2011-07-20 03:41:06 +0000834 s.PutCString(" ()");
835 break;
836
Greg Clayton7b139222011-07-21 01:12:01 +0000837 case KDP_RESUMECPUS:
Greg Clayton234981a2011-07-20 03:41:06 +0000838 {
839 const uint32_t cpu_mask = packet.GetU32 (&offset);
840 s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask);
841 }
Greg Clayton0fa51242011-07-19 03:57:15 +0000842 break;
843
Greg Clayton7b139222011-07-21 01:12:01 +0000844 case KDP_READMEM:
Greg Clayton0fa51242011-07-19 03:57:15 +0000845 {
846 const uint32_t addr = packet.GetU32 (&offset);
847 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000848 s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size);
Greg Clayton234981a2011-07-20 03:41:06 +0000849 m_last_read_memory_addr = addr;
Greg Clayton0fa51242011-07-19 03:57:15 +0000850 }
851 break;
852
Greg Clayton7b139222011-07-21 01:12:01 +0000853 case KDP_WRITEMEM:
Greg Claytonec15f502011-07-20 01:32:50 +0000854 {
855 const uint32_t addr = packet.GetU32 (&offset);
856 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000857 s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size);
Greg Claytonec15f502011-07-20 01:32:50 +0000858 if (size > 0)
859 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
860 }
861 break;
862
Greg Clayton7b139222011-07-21 01:12:01 +0000863 case KDP_READMEM64:
Greg Clayton0fa51242011-07-19 03:57:15 +0000864 {
865 const uint64_t addr = packet.GetU64 (&offset);
866 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000867 s.Printf(" (addr = 0x%16.16llx, size = %u)", addr, size);
Greg Clayton234981a2011-07-20 03:41:06 +0000868 m_last_read_memory_addr = addr;
Greg Clayton0fa51242011-07-19 03:57:15 +0000869 }
870 break;
871
Greg Clayton7b139222011-07-21 01:12:01 +0000872 case KDP_WRITEMEM64:
Greg Claytonec15f502011-07-20 01:32:50 +0000873 {
874 const uint64_t addr = packet.GetU64 (&offset);
875 const uint32_t size = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000876 s.Printf(" (addr = 0x%16.16llx, size = %u, bytes = \n", addr, size);
Greg Claytonec15f502011-07-20 01:32:50 +0000877 if (size > 0)
878 DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
879 }
880 break;
881
Greg Clayton7b139222011-07-21 01:12:01 +0000882 case KDP_READREGS:
Greg Clayton0fa51242011-07-19 03:57:15 +0000883 {
884 const uint32_t cpu = packet.GetU32 (&offset);
885 const uint32_t flavor = packet.GetU32 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000886 s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor);
Greg Clayton0fa51242011-07-19 03:57:15 +0000887 }
888 break;
889
Greg Clayton7b139222011-07-21 01:12:01 +0000890 case KDP_WRITEREGS:
Greg Claytonec15f502011-07-20 01:32:50 +0000891 {
892 const uint32_t cpu = packet.GetU32 (&offset);
893 const uint32_t flavor = packet.GetU32 (&offset);
894 const uint32_t nbytes = packet.GetByteSize() - offset;
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000895 s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor);
Greg Claytonec15f502011-07-20 01:32:50 +0000896 if (nbytes > 0)
897 packet.Dump (&s, // Stream to dump to
898 offset, // Offset within "packet"
899 eFormatHex, // Format to use
900 m_addr_byte_size, // Size of each item in bytes
901 nbytes / m_addr_byte_size, // Number of items
902 16 / m_addr_byte_size, // Number per line
903 LLDB_INVALID_ADDRESS, // Don't show addresses before each line
904 0, 0); // No bitfields
905 }
906 break;
907
Greg Claytonec15f502011-07-20 01:32:50 +0000908
Greg Clayton7b139222011-07-21 01:12:01 +0000909 case KDP_BREAKPOINT_SET:
910 case KDP_BREAKPOINT_REMOVE:
Greg Clayton234981a2011-07-20 03:41:06 +0000911 {
912 const uint32_t addr = packet.GetU32 (&offset);
913 s.Printf(" (addr = 0x%8.8x)", addr);
914 }
915 break;
916
Greg Clayton7b139222011-07-21 01:12:01 +0000917 case KDP_BREAKPOINT_SET64:
918 case KDP_BREAKPOINT_REMOVE64:
Greg Clayton234981a2011-07-20 03:41:06 +0000919 {
920 const uint64_t addr = packet.GetU64 (&offset);
921 s.Printf(" (addr = 0x%16.16llx)", addr);
922 }
923 break;
924
925
Greg Clayton7b139222011-07-21 01:12:01 +0000926 case KDP_LOAD:
Greg Clayton234981a2011-07-20 03:41:06 +0000927 {
928 const char *path = packet.GetCStr(&offset);
929 s.Printf(" (path = \"%s\")", path);
930 }
931 break;
932
Greg Clayton7b139222011-07-21 01:12:01 +0000933 case KDP_EXCEPTION:
Greg Clayton234981a2011-07-20 03:41:06 +0000934 {
935 const uint32_t count = packet.GetU32 (&offset);
936
937 s.Printf(" (count = %u:", count);
938 for (uint32_t i=0; i<count; ++i)
939 {
940 const uint32_t cpu = packet.GetU32 (&offset);
941 const uint32_t exc = packet.GetU32 (&offset);
942 const uint32_t code = packet.GetU32 (&offset);
943 const uint32_t subcode = packet.GetU32 (&offset);
944 const char *exc_cstr = NULL;
945 switch (exc)
946 {
947 case 1: exc_cstr = "EXC_BAD_ACCESS"; break;
948 case 2: exc_cstr = "EXC_BAD_INSTRUCTION"; break;
949 case 3: exc_cstr = "EXC_ARITHMETIC"; break;
950 case 4: exc_cstr = "EXC_EMULATION"; break;
951 case 5: exc_cstr = "EXC_SOFTWARE"; break;
952 case 6: exc_cstr = "EXC_BREAKPOINT"; break;
953 case 7: exc_cstr = "EXC_SYSCALL"; break;
954 case 8: exc_cstr = "EXC_MACH_SYSCALL"; break;
955 case 9: exc_cstr = "EXC_RPC_ALERT"; break;
956 case 10: exc_cstr = "EXC_CRASH"; break;
957 default:
958 break;
959 }
960
961 s.Printf ("\n cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)\n",
962 cpu, exc_cstr, exc, code, code, subcode, subcode);
963 }
964 }
965 break;
966
Greg Clayton7b139222011-07-21 01:12:01 +0000967 case KDP_TERMINATION:
Greg Clayton234981a2011-07-20 03:41:06 +0000968 {
969 const uint32_t term_code = packet.GetU32 (&offset);
970 const uint32_t exit_code = packet.GetU32 (&offset);
971 s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code);
972 }
Greg Clayton0fa51242011-07-19 03:57:15 +0000973 break;
974
Greg Clayton7b139222011-07-21 01:12:01 +0000975 case KDP_REATTACH:
Greg Clayton0fa51242011-07-19 03:57:15 +0000976 {
977 const uint16_t reply_port = packet.GetU16 (&offset);
Greg Clayton1bc04ed2011-07-29 22:26:36 +0000978 s.Printf(" (reply_port = %u)", reply_port);
Greg Clayton0fa51242011-07-19 03:57:15 +0000979 }
980 break;
Greg Clayton0fa51242011-07-19 03:57:15 +0000981 }
982 }
983 }
984 else
985 {
986 error_desc = "error: invalid packet command: ";
987 }
988 }
989
990 if (error_desc)
991 {
992 s.PutCString (error_desc);
993
994 packet.Dump (&s, // Stream to dump to
995 0, // Offset into "packet"
996 eFormatBytes, // Dump as hex bytes
997 1, // Size of each item is 1 for single bytes
998 packet.GetByteSize(), // Number of bytes
999 UINT32_MAX, // Num bytes per line
1000 LLDB_INVALID_ADDRESS, // Base address
1001 0, 0); // Bitfield info set to not do anything bitfield related
1002 }
1003}
1004
1005uint32_t
1006CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
1007 uint32_t flavor,
1008 void *dst,
1009 uint32_t dst_len,
1010 Error &error)
1011{
1012 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001013 const CommandType command = KDP_READREGS;
Greg Clayton0fa51242011-07-19 03:57:15 +00001014 // Size is header + 4 byte cpu and 4 byte flavor
1015 const uint32_t command_length = 8 + 4 + 4;
1016 const uint32_t request_sequence_id = m_request_sequence_id;
1017 MakeRequestPacketHeader (command, request_packet, command_length);
1018 request_packet.PutHex32 (cpu);
1019 request_packet.PutHex32 (flavor);
1020 DataExtractor reply_packet;
1021 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1022 {
Greg Clayton0fa51242011-07-19 03:57:15 +00001023 uint32_t offset = 8;
1024 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1025 uint32_t src_len = reply_packet.GetByteSize() - 12;
1026
1027 if (src_len > 0)
1028 {
1029 const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
1030 const void *src = reply_packet.GetData(&offset, bytes_to_copy);
1031 if (src)
1032 {
1033 ::memcpy (dst, src, bytes_to_copy);
1034 error.Clear();
1035 // Return the number of bytes we could have returned regardless if
1036 // we copied them or not, just so we know when things don't match up
1037 return src_len;
1038 }
1039 }
1040 if (kdp_error)
1041 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
1042 else
1043 error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
1044 }
1045 return 0;
1046}
1047
Greg Clayton234981a2011-07-20 03:41:06 +00001048
1049bool
1050CommunicationKDP::SendRequestResume (uint32_t cpu_mask)
1051{
1052 if (cpu_mask == 0)
1053 cpu_mask = GetCPUMask();
1054 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001055 const CommandType command = KDP_RESUMECPUS;
Greg Clayton234981a2011-07-20 03:41:06 +00001056 const uint32_t command_length = 12;
1057 const uint32_t request_sequence_id = m_request_sequence_id;
1058 MakeRequestPacketHeader (command, request_packet, command_length);
1059 request_packet.PutHex32(cpu_mask);
1060
1061 DataExtractor reply_packet;
1062 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1063 return true;
1064 return false;
1065}
1066
1067bool
1068CommunicationKDP::SendRequestBreakpoint (bool set, addr_t addr)
1069{
1070 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
1071 bool use_64 = (GetVersion() >= 11);
1072 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
Greg Clayton7b139222011-07-21 01:12:01 +00001073 const CommandType command = set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET ):
1074 (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE);
Greg Clayton234981a2011-07-20 03:41:06 +00001075
1076 const uint32_t command_length = 8 + command_addr_byte_size;
1077 const uint32_t request_sequence_id = m_request_sequence_id;
1078 MakeRequestPacketHeader (command, request_packet, command_length);
1079 request_packet.PutMaxHex64 (addr, command_addr_byte_size);
1080
1081 DataExtractor reply_packet;
1082 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
Greg Clayton1bc04ed2011-07-29 22:26:36 +00001083 {
1084 uint32_t offset = 8;
1085 uint32_t kdp_error = reply_packet.GetU32 (&offset);
1086 if (kdp_error == 0)
1087 return true;
1088 }
Greg Clayton234981a2011-07-20 03:41:06 +00001089 return false;
1090}
1091
1092bool
1093CommunicationKDP::SendRequestSuspend ()
1094{
1095 PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
Greg Clayton7b139222011-07-21 01:12:01 +00001096 const CommandType command = KDP_SUSPEND;
Greg Clayton234981a2011-07-20 03:41:06 +00001097 const uint32_t command_length = 8;
1098 const uint32_t request_sequence_id = m_request_sequence_id;
1099 MakeRequestPacketHeader (command, request_packet, command_length);
1100 DataExtractor reply_packet;
1101 if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
1102 return true;
1103 return false;
1104}
1105