blob: 1a75326f3b208cf489371fae17f399519efb0458 [file] [log] [blame]
Greg Clayton59ec5122011-07-15 18:02:58 +00001//===-- CommunicationKDP.cpp ------------------------------------*- C++ -*-===//
Greg Claytonf9765ac2011-07-15 03:27:12 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Greg Claytonf9765ac2011-07-15 03:27:12 +00006//
7//===----------------------------------------------------------------------===//
8
Greg Claytonf9765ac2011-07-15 03:27:12 +00009#include "CommunicationKDP.h"
10
Jason Molenda4bd4e7e2012-09-29 04:02:01 +000011#include <errno.h>
Greg Claytonf9765ac2011-07-15 03:27:12 +000012#include <limits.h>
13#include <string.h>
14
Greg Claytona63d08c2011-07-19 03:57:15 +000015
Zachary Turner9739a552017-03-03 23:52:09 +000016#include "lldb/Core/DumpDataExtractor.h"
Greg Claytonf9765ac2011-07-15 03:27:12 +000017#include "lldb/Host/Host.h"
Greg Claytonf9765ac2011-07-15 03:27:12 +000018#include "lldb/Target/Process.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000019#include "lldb/Utility/DataBufferHeap.h"
20#include "lldb/Utility/DataExtractor.h"
Zachary Turner5713a052017-03-22 18:40:07 +000021#include "lldb/Utility/FileSpec.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000022#include "lldb/Utility/Log.h"
Pavel Labathd821c992018-08-07 11:07:21 +000023#include "lldb/Utility/State.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000024#include "lldb/Utility/UUID.h"
Greg Claytonf9765ac2011-07-15 03:27:12 +000025
Greg Claytonf9765ac2011-07-15 03:27:12 +000026#include "ProcessKDPLog.h"
27
Greg Claytonf9765ac2011-07-15 03:27:12 +000028using namespace lldb;
29using namespace lldb_private;
30
Greg Claytonf9765ac2011-07-15 03:27:12 +000031// CommunicationKDP constructor
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +000032CommunicationKDP::CommunicationKDP(const char *comm_name)
Kate Stoneb9c1b512016-09-06 20:57:50 +000033 : Communication(comm_name), m_addr_byte_size(4),
34 m_byte_order(eByteOrderLittle), m_packet_timeout(5), m_sequence_mutex(),
35 m_is_running(false), m_session_key(0u), m_request_sequence_id(0u),
36 m_exception_sequence_id(0u), m_kdp_version_version(0u),
37 m_kdp_version_feature(0u), m_kdp_hostinfo_cpu_mask(0u),
38 m_kdp_hostinfo_cpu_type(0u), m_kdp_hostinfo_cpu_subtype(0u) {}
Greg Claytonf9765ac2011-07-15 03:27:12 +000039
Greg Claytonf9765ac2011-07-15 03:27:12 +000040// Destructor
Kate Stoneb9c1b512016-09-06 20:57:50 +000041CommunicationKDP::~CommunicationKDP() {
42 if (IsConnected()) {
43 Disconnect();
44 }
Greg Claytonf9765ac2011-07-15 03:27:12 +000045}
46
Kate Stoneb9c1b512016-09-06 20:57:50 +000047bool CommunicationKDP::SendRequestPacket(
48 const PacketStreamType &request_packet) {
49 std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex);
50 return SendRequestPacketNoLock(request_packet);
Greg Claytonf9765ac2011-07-15 03:27:12 +000051}
52
Kate Stoneb9c1b512016-09-06 20:57:50 +000053void CommunicationKDP::MakeRequestPacketHeader(CommandType request_type,
54 PacketStreamType &request_packet,
55 uint16_t request_length) {
56 request_packet.Clear();
57 request_packet.PutHex8(request_type |
58 ePacketTypeRequest); // Set the request type
59 request_packet.PutHex8(m_request_sequence_id++); // Sequence number
60 request_packet.PutHex16(
61 request_length); // Length of the packet including this header
62 request_packet.PutHex32(m_session_key); // Session key
Greg Claytonf9765ac2011-07-15 03:27:12 +000063}
64
Kate Stoneb9c1b512016-09-06 20:57:50 +000065bool CommunicationKDP::SendRequestAndGetReply(
66 const CommandType command, const PacketStreamType &request_packet,
67 DataExtractor &reply_packet) {
68 if (IsRunning()) {
69 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS));
70 if (log) {
71 PacketStreamType log_strm;
72 DumpPacket(log_strm, request_packet.GetData(), request_packet.GetSize());
73 log->Printf("error: kdp running, not sending packet: %.*s",
74 (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton97d5cf02012-09-25 02:40:06 +000075 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000076 return false;
77 }
Greg Clayton4df8ddf2011-07-16 03:19:08 +000078
Kate Stoneb9c1b512016-09-06 20:57:50 +000079 std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex);
Greg Clayton97d5cf02012-09-25 02:40:06 +000080#ifdef LLDB_CONFIGURATION_DEBUG
Kate Stoneb9c1b512016-09-06 20:57:50 +000081 // NOTE: this only works for packets that are in native endian byte order
82 assert(request_packet.GetSize() ==
Adrian Prantla01e0242017-12-19 22:54:37 +000083 *((const uint16_t *)(request_packet.GetData() + 2)));
Greg Clayton97d5cf02012-09-25 02:40:06 +000084#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +000085 lldb::offset_t offset = 1;
86 const uint32_t num_retries = 3;
87 for (uint32_t i = 0; i < num_retries; ++i) {
88 if (SendRequestPacketNoLock(request_packet)) {
89 const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1];
Jonas Devlieghere09ad8c82019-05-24 00:44:33 +000090 while (true) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000091 if (WaitForPacketWithTimeoutMicroSecondsNoLock(
Pavel Labath5cddd602016-11-02 10:13:54 +000092 reply_packet,
93 std::chrono::microseconds(GetPacketTimeout()).count())) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000094 offset = 0;
95 const uint8_t reply_command = reply_packet.GetU8(&offset);
96 const uint8_t reply_sequence_id = reply_packet.GetU8(&offset);
97 if (request_sequence_id == reply_sequence_id) {
98 // The sequent ID was correct, now verify we got the response we
99 // were looking for
100 if ((reply_command & eCommandTypeMask) == command) {
101 // Success
102 if (command == KDP_RESUMECPUS)
103 m_is_running.SetValue(true, eBroadcastAlways);
104 return true;
105 } else {
106 // Failed to get the correct response, bail
107 reply_packet.Clear();
108 return false;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000109 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110 } else if (reply_sequence_id > request_sequence_id) {
111 // Sequence ID was greater than the sequence ID of the packet we
Adrian Prantl05097242018-04-30 16:49:04 +0000112 // sent, something is really wrong...
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113 reply_packet.Clear();
114 return false;
115 } else {
Adrian Prantl05097242018-04-30 16:49:04 +0000116 // The reply sequence ID was less than our current packet's
117 // sequence ID so we should keep trying to get a response because
118 // this was a response for a previous packet that we must have
119 // retried.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120 }
121 } else {
122 // Break and retry sending the packet as we didn't get a response due
123 // to timeout
124 break;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000125 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 }
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000127 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128 }
129 reply_packet.Clear();
130 return false;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000131}
Greg Claytonf9765ac2011-07-15 03:27:12 +0000132
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133bool CommunicationKDP::SendRequestPacketNoLock(
134 const PacketStreamType &request_packet) {
135 if (IsConnected()) {
136 const char *packet_data = request_packet.GetData();
137 const size_t packet_size = request_packet.GetSize();
Greg Claytonf9765ac2011-07-15 03:27:12 +0000138
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS));
140 if (log) {
141 PacketStreamType log_strm;
142 DumpPacket(log_strm, packet_data, packet_size);
143 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton57508022011-07-15 16:31:38 +0000144 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145 ConnectionStatus status = eConnectionStatusSuccess;
146
147 size_t bytes_written = Write(packet_data, packet_size, status, NULL);
148
149 if (bytes_written == packet_size)
150 return true;
151
152 if (log)
153 log->Printf("error: failed to send packet entire packet %" PRIu64
154 " of %" PRIu64 " bytes sent",
155 (uint64_t)bytes_written, (uint64_t)packet_size);
156 }
157 return false;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000158}
159
Kate Stoneb9c1b512016-09-06 20:57:50 +0000160bool CommunicationKDP::GetSequenceMutex(
161 std::unique_lock<std::recursive_mutex> &lock) {
162 return (lock = std::unique_lock<std::recursive_mutex>(m_sequence_mutex,
163 std::try_to_lock))
164 .owns_lock();
Greg Claytonf9765ac2011-07-15 03:27:12 +0000165}
166
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167bool CommunicationKDP::WaitForNotRunningPrivate(
168 const std::chrono::microseconds &timeout) {
Pavel Labath38d67db2018-05-03 15:33:41 +0000169 return m_is_running.WaitForValueEqualTo(false, timeout);
Greg Claytonf9765ac2011-07-15 03:27:12 +0000170}
171
172size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds(DataExtractor &packet,
174 uint32_t timeout_usec) {
175 std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex);
176 return WaitForPacketWithTimeoutMicroSecondsNoLock(packet, timeout_usec);
Greg Claytonf9765ac2011-07-15 03:27:12 +0000177}
178
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock(
180 DataExtractor &packet, uint32_t timeout_usec) {
181 uint8_t buffer[8192];
Zachary Turner97206d52017-05-12 04:51:55 +0000182 Status error;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000183
Pavel Labath250858a2017-02-06 21:46:22 +0000184 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS));
Greg Claytonf9765ac2011-07-15 03:27:12 +0000185
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186 // Check for a packet from our cache first without trying any reading...
187 if (CheckForPacket(NULL, 0, packet))
188 return packet.GetByteSize();
189
190 bool timed_out = false;
191 while (IsConnected() && !timed_out) {
192 lldb::ConnectionStatus status = eConnectionStatusNoConnection;
Pavel Labathce8d6d92016-11-25 14:43:37 +0000193 size_t bytes_read = Read(buffer, sizeof(buffer),
194 timeout_usec == UINT32_MAX
195 ? Timeout<std::micro>(llvm::None)
196 : std::chrono::microseconds(timeout_usec),
197 status, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000198
Pavel Labath250858a2017-02-06 21:46:22 +0000199 LLDB_LOGV(log,
200 "Read (buffer, sizeof(buffer), timeout_usec = 0x{0:x}, "
201 "status = {1}, error = {2}) => bytes_read = {4}",
202 timeout_usec,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203 Communication::ConnectionStatusAsCString(status),
Pavel Labath250858a2017-02-06 21:46:22 +0000204 error, bytes_read);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000205
206 if (bytes_read > 0) {
207 if (CheckForPacket(buffer, bytes_read, packet))
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000208 return packet.GetByteSize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000209 } else {
210 switch (status) {
211 case eConnectionStatusInterrupted:
212 case eConnectionStatusTimedOut:
213 timed_out = true;
214 break;
215 case eConnectionStatusSuccess:
216 // printf ("status = success but error = %s\n",
217 // error.AsCString("<invalid>"));
218 break;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000219
Kate Stoneb9c1b512016-09-06 20:57:50 +0000220 case eConnectionStatusEndOfFile:
221 case eConnectionStatusNoConnection:
222 case eConnectionStatusLostConnection:
223 case eConnectionStatusError:
224 Disconnect();
225 break;
226 }
Greg Claytonf9765ac2011-07-15 03:27:12 +0000227 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000228 }
229 packet.Clear();
230 return 0;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000231}
232
Kate Stoneb9c1b512016-09-06 20:57:50 +0000233bool CommunicationKDP::CheckForPacket(const uint8_t *src, size_t src_len,
234 DataExtractor &packet) {
235 // Put the packet data into the buffer in a thread safe fashion
236 std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex);
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000237
Kate Stoneb9c1b512016-09-06 20:57:50 +0000238 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS));
Greg Claytonf9765ac2011-07-15 03:27:12 +0000239
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240 if (src && src_len > 0) {
241 if (log && log->GetVerbose()) {
242 PacketStreamType log_strm;
Zachary Turner9739a552017-03-03 23:52:09 +0000243 DumpHexBytes(&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000244 log->Printf("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__,
245 (uint32_t)src_len, log_strm.GetData());
Greg Claytonf9765ac2011-07-15 03:27:12 +0000246 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000247 m_bytes.append((const char *)src, src_len);
248 }
Greg Claytonf9765ac2011-07-15 03:27:12 +0000249
Kate Stoneb9c1b512016-09-06 20:57:50 +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) {
253 packet.SetData(&m_bytes[0], bytes_available, m_byte_order);
254 lldb::offset_t offset = 0;
255 uint8_t reply_command = packet.GetU8(&offset);
256 switch (reply_command) {
257 case ePacketTypeRequest | KDP_EXCEPTION:
258 case ePacketTypeRequest | KDP_TERMINATION:
259 // We got an exception request, so be sure to send an ACK
260 {
261 PacketStreamType request_ack_packet(Stream::eBinary, m_addr_byte_size,
262 m_byte_order);
263 // Set the reply but and make the ACK packet
264 request_ack_packet.PutHex8(reply_command | ePacketTypeReply);
265 request_ack_packet.PutHex8(packet.GetU8(&offset));
266 request_ack_packet.PutHex16(packet.GetU16(&offset));
267 request_ack_packet.PutHex32(packet.GetU32(&offset));
268 m_is_running.SetValue(false, eBroadcastAlways);
269 // Ack to the exception or termination
270 SendRequestPacketNoLock(request_ack_packet);
271 }
272 // Fall through to case below to get packet contents
273 LLVM_FALLTHROUGH;
274 case ePacketTypeReply | KDP_CONNECT:
275 case ePacketTypeReply | KDP_DISCONNECT:
276 case ePacketTypeReply | KDP_HOSTINFO:
277 case ePacketTypeReply | KDP_VERSION:
278 case ePacketTypeReply | KDP_MAXBYTES:
279 case ePacketTypeReply | KDP_READMEM:
280 case ePacketTypeReply | KDP_WRITEMEM:
281 case ePacketTypeReply | KDP_READREGS:
282 case ePacketTypeReply | KDP_WRITEREGS:
283 case ePacketTypeReply | KDP_LOAD:
284 case ePacketTypeReply | KDP_IMAGEPATH:
285 case ePacketTypeReply | KDP_SUSPEND:
286 case ePacketTypeReply | KDP_RESUMECPUS:
287 case ePacketTypeReply | KDP_BREAKPOINT_SET:
288 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE:
289 case ePacketTypeReply | KDP_REGIONS:
290 case ePacketTypeReply | KDP_REATTACH:
291 case ePacketTypeReply | KDP_HOSTREBOOT:
292 case ePacketTypeReply | KDP_READMEM64:
293 case ePacketTypeReply | KDP_WRITEMEM64:
294 case ePacketTypeReply | KDP_BREAKPOINT_SET64:
295 case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64:
296 case ePacketTypeReply | KDP_KERNELVERSION:
297 case ePacketTypeReply | KDP_READPHYSMEM64:
298 case ePacketTypeReply | KDP_WRITEPHYSMEM64:
299 case ePacketTypeReply | KDP_READIOPORT:
300 case ePacketTypeReply | KDP_WRITEIOPORT:
301 case ePacketTypeReply | KDP_READMSR64:
302 case ePacketTypeReply | KDP_WRITEMSR64:
303 case ePacketTypeReply | KDP_DUMPINFO: {
304 offset = 2;
305 const uint16_t length = packet.GetU16(&offset);
306 if (length <= bytes_available) {
Adrian Prantl05097242018-04-30 16:49:04 +0000307 // We have an entire packet ready, we need to copy the data bytes into
308 // a buffer that will be owned by the packet and erase the bytes from
309 // our communcation buffer "m_bytes"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000310 packet.SetData(DataBufferSP(new DataBufferHeap(&m_bytes[0], length)));
311 m_bytes.erase(0, length);
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000312
Kate Stoneb9c1b512016-09-06 20:57:50 +0000313 if (log) {
314 PacketStreamType log_strm;
315 DumpPacket(log_strm, packet);
316
317 log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000318 }
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000319 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000320 }
321 } break;
322
323 default:
Adrian Prantl05097242018-04-30 16:49:04 +0000324 // Unrecognized reply command byte, erase this byte and try to get back
325 // on track
Kate Stoneb9c1b512016-09-06 20:57:50 +0000326 if (log)
327 log->Printf("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
328 __FUNCTION__, (uint8_t)m_bytes[0]);
329 m_bytes.erase(0, 1);
330 break;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000331 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000332 }
333 packet.Clear();
334 return false;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000335}
336
Kate Stoneb9c1b512016-09-06 20:57:50 +0000337bool CommunicationKDP::SendRequestConnect(uint16_t reply_port,
338 uint16_t exc_port,
339 const char *greeting) {
340 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
341 m_byte_order);
342 if (greeting == NULL)
343 greeting = "";
344
345 const CommandType command = KDP_CONNECT;
346 // Length is 82 uint16_t and the length of the greeting C string with the
347 // terminating NULL
348 const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
349 MakeRequestPacketHeader(command, request_packet, command_length);
350 // Always send connect ports as little endian
351 request_packet.SetByteOrder(eByteOrderLittle);
352 request_packet.PutHex16(htons(reply_port));
353 request_packet.PutHex16(htons(exc_port));
354 request_packet.SetByteOrder(m_byte_order);
355 request_packet.PutCString(greeting);
356 DataExtractor reply_packet;
357 return SendRequestAndGetReply(command, request_packet, reply_packet);
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000358}
359
Kate Stoneb9c1b512016-09-06 20:57:50 +0000360void CommunicationKDP::ClearKDPSettings() {
361 m_request_sequence_id = 0;
362 m_kdp_version_version = 0;
363 m_kdp_version_feature = 0;
364 m_kdp_hostinfo_cpu_mask = 0;
365 m_kdp_hostinfo_cpu_type = 0;
366 m_kdp_hostinfo_cpu_subtype = 0;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000367}
368
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369bool CommunicationKDP::SendRequestReattach(uint16_t reply_port) {
370 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
371 m_byte_order);
372 const CommandType command = KDP_REATTACH;
373 // Length is 8 bytes for the header plus 2 bytes for the reply UDP port
374 const uint32_t command_length = 8 + 2;
375 MakeRequestPacketHeader(command, request_packet, command_length);
376 // Always send connect ports as little endian
377 request_packet.SetByteOrder(eByteOrderLittle);
378 request_packet.PutHex16(htons(reply_port));
379 request_packet.SetByteOrder(m_byte_order);
380 DataExtractor reply_packet;
381 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
382 // Reset the sequence ID to zero for reattach
383 ClearKDPSettings();
384 lldb::offset_t offset = 4;
385 m_session_key = reply_packet.GetU32(&offset);
386 return true;
387 }
388 return false;
389}
390
391uint32_t CommunicationKDP::GetVersion() {
392 if (!VersionIsValid())
393 SendRequestVersion();
394 return m_kdp_version_version;
395}
396
397uint32_t CommunicationKDP::GetFeatureFlags() {
398 if (!VersionIsValid())
399 SendRequestVersion();
400 return m_kdp_version_feature;
401}
402
403bool CommunicationKDP::SendRequestVersion() {
404 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
405 m_byte_order);
406 const CommandType command = KDP_VERSION;
407 const uint32_t command_length = 8;
408 MakeRequestPacketHeader(command, request_packet, command_length);
409 DataExtractor reply_packet;
410 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
411 lldb::offset_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;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000417}
418
Kate Stoneb9c1b512016-09-06 20:57:50 +0000419uint32_t CommunicationKDP::GetCPUMask() {
420 if (!HostInfoIsValid())
421 SendRequestHostInfo();
422 return m_kdp_hostinfo_cpu_mask;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000423}
424
Kate Stoneb9c1b512016-09-06 20:57:50 +0000425uint32_t CommunicationKDP::GetCPUType() {
426 if (!HostInfoIsValid())
427 SendRequestHostInfo();
428 return m_kdp_hostinfo_cpu_type;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000429}
430
Kate Stoneb9c1b512016-09-06 20:57:50 +0000431uint32_t CommunicationKDP::GetCPUSubtype() {
432 if (!HostInfoIsValid())
433 SendRequestHostInfo();
434 return m_kdp_hostinfo_cpu_subtype;
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000435}
436
Kate Stoneb9c1b512016-09-06 20:57:50 +0000437lldb_private::UUID CommunicationKDP::GetUUID() {
438 UUID uuid;
439 if (GetKernelVersion() == NULL)
Jason Molenda4bd4e7e2012-09-29 04:02:01 +0000440 return uuid;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441
442 if (m_kernel_version.find("UUID=") == std::string::npos)
443 return uuid;
444
445 size_t p = m_kernel_version.find("UUID=") + strlen("UUID=");
446 std::string uuid_str = m_kernel_version.substr(p, 36);
447 if (uuid_str.size() < 32)
448 return uuid;
449
Pavel Labatha174bcb2018-06-21 15:24:39 +0000450 if (uuid.SetFromStringRef(uuid_str) == 0) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000451 UUID invalid_uuid;
452 return invalid_uuid;
453 }
454
455 return uuid;
Jason Molenda4bd4e7e2012-09-29 04:02:01 +0000456}
457
Kate Stoneb9c1b512016-09-06 20:57:50 +0000458bool CommunicationKDP::RemoteIsEFI() {
459 if (GetKernelVersion() == NULL)
Greg Clayton4df8ddf2011-07-16 03:19:08 +0000460 return false;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000461 return strncmp(m_kernel_version.c_str(), "EFI", 3) == 0;
Greg Clayton1d19a2f2012-10-19 22:22:57 +0000462}
463
Kate Stoneb9c1b512016-09-06 20:57:50 +0000464bool CommunicationKDP::RemoteIsDarwinKernel() {
465 if (GetKernelVersion() == NULL)
466 return false;
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000467 return m_kernel_version.find("Darwin Kernel") != std::string::npos;
Greg Clayton07e66e32011-07-20 03:41:06 +0000468}
469
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470lldb::addr_t CommunicationKDP::GetLoadAddress() {
471 if (GetKernelVersion() == NULL)
472 return LLDB_INVALID_ADDRESS;
Greg Clayton07e66e32011-07-20 03:41:06 +0000473
Kate Stoneb9c1b512016-09-06 20:57:50 +0000474 if (m_kernel_version.find("stext=") == std::string::npos)
475 return LLDB_INVALID_ADDRESS;
476 size_t p = m_kernel_version.find("stext=") + strlen("stext=");
477 if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x')
478 return LLDB_INVALID_ADDRESS;
479
480 addr_t kernel_load_address;
481 errno = 0;
482 kernel_load_address = ::strtoul(m_kernel_version.c_str() + p, NULL, 16);
483 if (errno != 0 || kernel_load_address == 0)
484 return LLDB_INVALID_ADDRESS;
485
486 return kernel_load_address;
487}
488
489bool CommunicationKDP::SendRequestHostInfo() {
490 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
491 m_byte_order);
492 const CommandType command = KDP_HOSTINFO;
493 const uint32_t command_length = 8;
494 MakeRequestPacketHeader(command, request_packet, command_length);
495 DataExtractor reply_packet;
496 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
497 lldb::offset_t offset = 8;
498 m_kdp_hostinfo_cpu_mask = reply_packet.GetU32(&offset);
499 m_kdp_hostinfo_cpu_type = reply_packet.GetU32(&offset);
500 m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32(&offset);
501
502 ArchSpec kernel_arch;
503 kernel_arch.SetArchitecture(eArchTypeMachO, m_kdp_hostinfo_cpu_type,
504 m_kdp_hostinfo_cpu_subtype);
505
506 m_addr_byte_size = kernel_arch.GetAddressByteSize();
507 m_byte_order = kernel_arch.GetByteOrder();
508 return true;
509 }
510 return false;
511}
512
513const char *CommunicationKDP::GetKernelVersion() {
514 if (m_kernel_version.empty())
515 SendRequestKernelVersion();
516 return m_kernel_version.c_str();
517}
518
519bool CommunicationKDP::SendRequestKernelVersion() {
520 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
521 m_byte_order);
522 const CommandType command = KDP_KERNELVERSION;
523 const uint32_t command_length = 8;
524 MakeRequestPacketHeader(command, request_packet, command_length);
525 DataExtractor reply_packet;
526 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
527 const char *kernel_version_cstr = reply_packet.PeekCStr(8);
528 if (kernel_version_cstr && kernel_version_cstr[0])
529 m_kernel_version.assign(kernel_version_cstr);
530 return true;
531 }
532 return false;
533}
534
535bool CommunicationKDP::SendRequestDisconnect() {
536 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
537 m_byte_order);
538 const CommandType command = KDP_DISCONNECT;
539 const uint32_t command_length = 8;
540 MakeRequestPacketHeader(command, request_packet, command_length);
541 DataExtractor reply_packet;
542 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
543 // Are we supposed to get a reply for disconnect?
544 }
545 ClearKDPSettings();
546 return true;
547}
548
549uint32_t CommunicationKDP::SendRequestReadMemory(lldb::addr_t addr, void *dst,
550 uint32_t dst_len,
Zachary Turner97206d52017-05-12 04:51:55 +0000551 Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000552 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
553 m_byte_order);
554 bool use_64 = (GetVersion() >= 11);
555 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
556 const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM;
557 // Size is header + address size + uint32_t length
558 const uint32_t command_length = 8 + command_addr_byte_size + 4;
559 MakeRequestPacketHeader(command, request_packet, command_length);
560 request_packet.PutMaxHex64(addr, command_addr_byte_size);
561 request_packet.PutHex32(dst_len);
562 DataExtractor reply_packet;
563 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
564 lldb::offset_t offset = 8;
565 uint32_t kdp_error = reply_packet.GetU32(&offset);
566 uint32_t src_len = reply_packet.GetByteSize() - 12;
567
568 if (src_len > 0) {
569 const void *src = reply_packet.GetData(&offset, src_len);
570 if (src) {
571 ::memcpy(dst, src, src_len);
572 error.Clear();
573 return src_len;
574 }
Greg Clayton5b442372011-07-29 22:26:36 +0000575 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000576 if (kdp_error)
577 error.SetErrorStringWithFormat("kdp read memory failed (error %u)",
578 kdp_error);
579 else
580 error.SetErrorString("kdp read memory failed");
581 } else {
582 error.SetErrorString("failed to send packet");
583 }
584 return 0;
Greg Clayton07e66e32011-07-20 03:41:06 +0000585}
586
Kate Stoneb9c1b512016-09-06 20:57:50 +0000587uint32_t CommunicationKDP::SendRequestWriteMemory(lldb::addr_t addr,
588 const void *src,
589 uint32_t src_len,
Zachary Turner97206d52017-05-12 04:51:55 +0000590 Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000591 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
592 m_byte_order);
593 bool use_64 = (GetVersion() >= 11);
594 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
595 const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM;
596 // Size is header + address size + uint32_t length
597 const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len;
598 MakeRequestPacketHeader(command, request_packet, command_length);
599 request_packet.PutMaxHex64(addr, command_addr_byte_size);
600 request_packet.PutHex32(src_len);
601 request_packet.PutRawBytes(src, src_len);
602
603 DataExtractor reply_packet;
604 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
605 lldb::offset_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)",
609 kdp_error);
610 else {
611 error.Clear();
612 return src_len;
613 }
614 } else {
615 error.SetErrorString("failed to send packet");
616 }
617 return 0;
Greg Clayton07e66e32011-07-20 03:41:06 +0000618}
619
Kate Stoneb9c1b512016-09-06 20:57:50 +0000620bool CommunicationKDP::SendRawRequest(
621 uint8_t command_byte,
622 const void *src, // Raw packet payload bytes
623 uint32_t src_len, // Raw packet payload length
Zachary Turner97206d52017-05-12 04:51:55 +0000624 DataExtractor &reply_packet, Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000625 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
626 m_byte_order);
627 // Size is header + address size + uint32_t length
628 const uint32_t command_length = 8 + src_len;
629 const CommandType command = (CommandType)command_byte;
630 MakeRequestPacketHeader(command, request_packet, command_length);
631 request_packet.PutRawBytes(src, src_len);
632
633 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
634 lldb::offset_t offset = 8;
635 uint32_t kdp_error = reply_packet.GetU32(&offset);
636 if (kdp_error && (command_byte != KDP_DUMPINFO))
637 error.SetErrorStringWithFormat("request packet 0x%8.8x failed (error %u)",
638 command_byte, kdp_error);
639 else {
640 error.Clear();
641 return true;
642 }
643 } else {
644 error.SetErrorString("failed to send packet");
645 }
646 return false;
647}
648
649const char *CommunicationKDP::GetCommandAsCString(uint8_t command) {
650 switch (command) {
651 case KDP_CONNECT:
652 return "KDP_CONNECT";
653 case KDP_DISCONNECT:
654 return "KDP_DISCONNECT";
655 case KDP_HOSTINFO:
656 return "KDP_HOSTINFO";
657 case KDP_VERSION:
658 return "KDP_VERSION";
659 case KDP_MAXBYTES:
660 return "KDP_MAXBYTES";
661 case KDP_READMEM:
662 return "KDP_READMEM";
663 case KDP_WRITEMEM:
664 return "KDP_WRITEMEM";
665 case KDP_READREGS:
666 return "KDP_READREGS";
667 case KDP_WRITEREGS:
668 return "KDP_WRITEREGS";
669 case KDP_LOAD:
670 return "KDP_LOAD";
671 case KDP_IMAGEPATH:
672 return "KDP_IMAGEPATH";
673 case KDP_SUSPEND:
674 return "KDP_SUSPEND";
675 case KDP_RESUMECPUS:
676 return "KDP_RESUMECPUS";
677 case KDP_EXCEPTION:
678 return "KDP_EXCEPTION";
679 case KDP_TERMINATION:
680 return "KDP_TERMINATION";
681 case KDP_BREAKPOINT_SET:
682 return "KDP_BREAKPOINT_SET";
683 case KDP_BREAKPOINT_REMOVE:
684 return "KDP_BREAKPOINT_REMOVE";
685 case KDP_REGIONS:
686 return "KDP_REGIONS";
687 case KDP_REATTACH:
688 return "KDP_REATTACH";
689 case KDP_HOSTREBOOT:
690 return "KDP_HOSTREBOOT";
691 case KDP_READMEM64:
692 return "KDP_READMEM64";
693 case KDP_WRITEMEM64:
694 return "KDP_WRITEMEM64";
695 case KDP_BREAKPOINT_SET64:
696 return "KDP_BREAKPOINT64_SET";
697 case KDP_BREAKPOINT_REMOVE64:
698 return "KDP_BREAKPOINT64_REMOVE";
699 case KDP_KERNELVERSION:
700 return "KDP_KERNELVERSION";
701 case KDP_READPHYSMEM64:
702 return "KDP_READPHYSMEM64";
703 case KDP_WRITEPHYSMEM64:
704 return "KDP_WRITEPHYSMEM64";
705 case KDP_READIOPORT:
706 return "KDP_READIOPORT";
707 case KDP_WRITEIOPORT:
708 return "KDP_WRITEIOPORT";
709 case KDP_READMSR64:
710 return "KDP_READMSR64";
711 case KDP_WRITEMSR64:
712 return "KDP_WRITEMSR64";
713 case KDP_DUMPINFO:
714 return "KDP_DUMPINFO";
715 }
716 return NULL;
717}
718
719void CommunicationKDP::DumpPacket(Stream &s, const void *data,
720 uint32_t data_len) {
721 DataExtractor extractor(data, data_len, m_byte_order, m_addr_byte_size);
722 DumpPacket(s, extractor);
723}
724
725void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) {
726 const char *error_desc = NULL;
727 if (packet.GetByteSize() < 8) {
728 error_desc = "error: invalid packet (too short): ";
729 } else {
730 lldb::offset_t offset = 0;
731 const uint8_t first_packet_byte = packet.GetU8(&offset);
732 const uint8_t sequence_id = packet.GetU8(&offset);
733 const uint16_t length = packet.GetU16(&offset);
734 const uint32_t key = packet.GetU32(&offset);
735 const CommandType command = ExtractCommand(first_packet_byte);
736 const char *command_name = GetCommandAsCString(command);
737 if (command_name) {
738 const bool is_reply = ExtractIsReply(first_packet_byte);
739 s.Printf("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ",
740 IsRunning(), is_reply ? "<--" : "-->", command_name,
741 first_packet_byte, sequence_id, length, key);
742
743 if (is_reply) {
744 // Dump request reply packets
745 switch (command) {
746 // Commands that return a single 32 bit error
747 case KDP_CONNECT:
748 case KDP_WRITEMEM:
749 case KDP_WRITEMEM64:
750 case KDP_BREAKPOINT_SET:
751 case KDP_BREAKPOINT_REMOVE:
752 case KDP_BREAKPOINT_SET64:
753 case KDP_BREAKPOINT_REMOVE64:
754 case KDP_WRITEREGS:
755 case KDP_LOAD:
756 case KDP_WRITEIOPORT:
757 case KDP_WRITEMSR64: {
758 const uint32_t error = packet.GetU32(&offset);
759 s.Printf(" (error=0x%8.8x)", error);
760 } break;
761
762 case KDP_DISCONNECT:
763 case KDP_REATTACH:
764 case KDP_HOSTREBOOT:
765 case KDP_SUSPEND:
766 case KDP_RESUMECPUS:
767 case KDP_EXCEPTION:
768 case KDP_TERMINATION:
769 // No return value for the reply, just the header to ack
770 s.PutCString(" ()");
771 break;
772
773 case KDP_HOSTINFO: {
774 const uint32_t cpu_mask = packet.GetU32(&offset);
775 const uint32_t cpu_type = packet.GetU32(&offset);
776 const uint32_t cpu_subtype = packet.GetU32(&offset);
777 s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)",
778 cpu_mask, cpu_type, cpu_subtype);
779 } break;
780
781 case KDP_VERSION: {
782 const uint32_t version = packet.GetU32(&offset);
783 const uint32_t feature = packet.GetU32(&offset);
784 s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature);
785 } break;
786
787 case KDP_REGIONS: {
788 const uint32_t region_count = packet.GetU32(&offset);
789 s.Printf(" (count = %u", region_count);
790 for (uint32_t i = 0; i < region_count; ++i) {
791 const addr_t region_addr = packet.GetPointer(&offset);
792 const uint32_t region_size = packet.GetU32(&offset);
793 const uint32_t region_prot = packet.GetU32(&offset);
794 s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64
795 " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }",
796 region_addr, region_addr, region_addr + region_size,
797 region_size, GetPermissionsAsCString(region_prot));
798 }
799 } break;
800
801 case KDP_READMEM:
802 case KDP_READMEM64:
803 case KDP_READPHYSMEM64: {
804 const uint32_t error = packet.GetU32(&offset);
805 const uint32_t count = packet.GetByteSize() - offset;
806 s.Printf(" (error = 0x%8.8x:\n", error);
807 if (count > 0)
Jim Inghamc963f202017-03-04 01:15:24 +0000808 DumpDataExtractor(packet,
809 &s, // Stream to dump to
810 offset, // Offset within "packet"
811 eFormatBytesWithASCII, // Format to use
812 1, // Size of each item
813 // in bytes
814 count, // Number of items
815 16, // Number per line
816 m_last_read_memory_addr, // Don't show addresses
817 // before each line
818 0, 0); // No bitfields
Kate Stoneb9c1b512016-09-06 20:57:50 +0000819 } break;
820
821 case KDP_READREGS: {
822 const uint32_t error = packet.GetU32(&offset);
823 const uint32_t count = packet.GetByteSize() - offset;
824 s.Printf(" (error = 0x%8.8x regs:\n", error);
825 if (count > 0)
Jim Inghamc963f202017-03-04 01:15:24 +0000826 DumpDataExtractor(packet,
827 &s, // Stream to dump to
828 offset, // Offset within "packet"
829 eFormatHex, // Format to use
830 m_addr_byte_size, // Size of each item
831 // in bytes
832 count / m_addr_byte_size, // Number of items
833 16 / m_addr_byte_size, // Number per line
834 LLDB_INVALID_ADDRESS,
835 // Don't
836 // show addresses before
837 // each line
838 0, 0); // No bitfields
Kate Stoneb9c1b512016-09-06 20:57:50 +0000839 } break;
840
841 case KDP_KERNELVERSION: {
842 const char *kernel_version = packet.PeekCStr(8);
843 s.Printf(" (version = \"%s\")", kernel_version);
844 } break;
845
846 case KDP_MAXBYTES: {
847 const uint32_t max_bytes = packet.GetU32(&offset);
848 s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes);
849 } break;
850 case KDP_IMAGEPATH: {
851 const char *path = packet.GetCStr(&offset);
852 s.Printf(" (path = \"%s\")", path);
853 } break;
854
855 case KDP_READIOPORT:
856 case KDP_READMSR64: {
857 const uint32_t error = packet.GetU32(&offset);
858 const uint32_t count = packet.GetByteSize() - offset;
859 s.Printf(" (error = 0x%8.8x io:\n", error);
860 if (count > 0)
Jim Inghamc963f202017-03-04 01:15:24 +0000861 DumpDataExtractor(packet,
862 &s, // Stream to dump to
863 offset, // Offset within "packet"
864 eFormatHex, // Format to use
865 1, // Size of each item in bytes
866 count, // Number of items
867 16, // Number per line
868 LLDB_INVALID_ADDRESS, // Don't show addresses
869 // before each line
870 0, 0); // No bitfields
Kate Stoneb9c1b512016-09-06 20:57:50 +0000871 } break;
872 case KDP_DUMPINFO: {
873 const uint32_t count = packet.GetByteSize() - offset;
874 s.Printf(" (count = %u, bytes = \n", count);
875 if (count > 0)
Jim Inghamc963f202017-03-04 01:15:24 +0000876 DumpDataExtractor(packet,
877 &s, // Stream to dump to
878 offset, // Offset within "packet"
879 eFormatHex, // Format to use
880 1, // Size of each item in
881 // bytes
882 count, // Number of items
883 16, // Number per line
884 LLDB_INVALID_ADDRESS, // Don't show addresses
885 // before each line
886 0, 0); // No bitfields
Kate Stoneb9c1b512016-09-06 20:57:50 +0000887
888 } break;
889
890 default:
891 s.Printf(" (add support for dumping this packet reply!!!");
892 break;
893 }
894 } else {
895 // Dump request packets
896 switch (command) {
897 case KDP_CONNECT: {
898 const uint16_t reply_port = ntohs(packet.GetU16(&offset));
899 const uint16_t exc_port = ntohs(packet.GetU16(&offset));
900 s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")",
901 reply_port, exc_port, packet.GetCStr(&offset));
902 } break;
903
904 case KDP_DISCONNECT:
905 case KDP_HOSTREBOOT:
906 case KDP_HOSTINFO:
907 case KDP_VERSION:
908 case KDP_REGIONS:
909 case KDP_KERNELVERSION:
910 case KDP_MAXBYTES:
911 case KDP_IMAGEPATH:
912 case KDP_SUSPEND:
913 // No args, just the header in the request...
914 s.PutCString(" ()");
915 break;
916
917 case KDP_RESUMECPUS: {
918 const uint32_t cpu_mask = packet.GetU32(&offset);
919 s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask);
920 } break;
921
922 case KDP_READMEM: {
923 const uint32_t addr = packet.GetU32(&offset);
924 const uint32_t size = packet.GetU32(&offset);
925 s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size);
926 m_last_read_memory_addr = addr;
927 } break;
928
929 case KDP_WRITEMEM: {
930 const uint32_t addr = packet.GetU32(&offset);
931 const uint32_t size = packet.GetU32(&offset);
932 s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size);
933 if (size > 0)
Zachary Turner9739a552017-03-03 23:52:09 +0000934 DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000935 } break;
936
937 case KDP_READMEM64: {
938 const uint64_t addr = packet.GetU64(&offset);
939 const uint32_t size = packet.GetU32(&offset);
940 s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size);
941 m_last_read_memory_addr = addr;
942 } break;
943
944 case KDP_READPHYSMEM64: {
945 const uint64_t addr = packet.GetU64(&offset);
946 const uint32_t size = packet.GetU32(&offset);
947 const uint32_t lcpu = packet.GetU16(&offset);
948 s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size,
949 lcpu);
950 m_last_read_memory_addr = addr;
951 } break;
952
953 case KDP_WRITEMEM64: {
954 const uint64_t addr = packet.GetU64(&offset);
955 const uint32_t size = packet.GetU32(&offset);
956 s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr,
957 size);
958 if (size > 0)
Zachary Turner9739a552017-03-03 23:52:09 +0000959 DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000960 } break;
961
962 case KDP_WRITEPHYSMEM64: {
963 const uint64_t addr = packet.GetU64(&offset);
964 const uint32_t size = packet.GetU32(&offset);
965 const uint32_t lcpu = packet.GetU16(&offset);
966 s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n",
967 addr, size, lcpu);
968 if (size > 0)
Zachary Turner9739a552017-03-03 23:52:09 +0000969 DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000970 } break;
971
972 case KDP_READREGS: {
973 const uint32_t cpu = packet.GetU32(&offset);
974 const uint32_t flavor = packet.GetU32(&offset);
975 s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor);
976 } break;
977
978 case KDP_WRITEREGS: {
979 const uint32_t cpu = packet.GetU32(&offset);
980 const uint32_t flavor = packet.GetU32(&offset);
981 const uint32_t nbytes = packet.GetByteSize() - offset;
982 s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor);
983 if (nbytes > 0)
Jim Inghamc963f202017-03-04 01:15:24 +0000984 DumpDataExtractor(packet,
985 &s, // Stream to dump to
986 offset, // Offset within
987 // "packet"
988 eFormatHex, // Format to use
989 m_addr_byte_size, // Size of each item in
990 // bytes
991 nbytes / m_addr_byte_size, // Number of items
992 16 / m_addr_byte_size, // Number per line
993 LLDB_INVALID_ADDRESS, // Don't show addresses
994 // before each line
995 0, 0); // No bitfields
Kate Stoneb9c1b512016-09-06 20:57:50 +0000996 } break;
997
998 case KDP_BREAKPOINT_SET:
999 case KDP_BREAKPOINT_REMOVE: {
1000 const uint32_t addr = packet.GetU32(&offset);
1001 s.Printf(" (addr = 0x%8.8x)", addr);
1002 } break;
1003
1004 case KDP_BREAKPOINT_SET64:
1005 case KDP_BREAKPOINT_REMOVE64: {
1006 const uint64_t addr = packet.GetU64(&offset);
1007 s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr);
1008 } break;
1009
1010 case KDP_LOAD: {
1011 const char *path = packet.GetCStr(&offset);
1012 s.Printf(" (path = \"%s\")", path);
1013 } break;
1014
1015 case KDP_EXCEPTION: {
1016 const uint32_t count = packet.GetU32(&offset);
1017
1018 for (uint32_t i = 0; i < count; ++i) {
1019 const uint32_t cpu = packet.GetU32(&offset);
1020 const uint32_t exc = packet.GetU32(&offset);
1021 const uint32_t code = packet.GetU32(&offset);
1022 const uint32_t subcode = packet.GetU32(&offset);
1023 const char *exc_cstr = NULL;
1024 switch (exc) {
1025 case 1:
1026 exc_cstr = "EXC_BAD_ACCESS";
1027 break;
1028 case 2:
1029 exc_cstr = "EXC_BAD_INSTRUCTION";
1030 break;
1031 case 3:
1032 exc_cstr = "EXC_ARITHMETIC";
1033 break;
1034 case 4:
1035 exc_cstr = "EXC_EMULATION";
1036 break;
1037 case 5:
1038 exc_cstr = "EXC_SOFTWARE";
1039 break;
1040 case 6:
1041 exc_cstr = "EXC_BREAKPOINT";
1042 break;
1043 case 7:
1044 exc_cstr = "EXC_SYSCALL";
1045 break;
1046 case 8:
1047 exc_cstr = "EXC_MACH_SYSCALL";
1048 break;
1049 case 9:
1050 exc_cstr = "EXC_RPC_ALERT";
1051 break;
1052 case 10:
1053 exc_cstr = "EXC_CRASH";
1054 break;
1055 default:
1056 break;
1057 }
1058
1059 s.Printf("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), "
1060 "subcode = %u (0x%8.8x)} ",
1061 cpu, exc_cstr, exc, code, code, subcode, subcode);
1062 }
1063 } break;
1064
1065 case KDP_TERMINATION: {
1066 const uint32_t term_code = packet.GetU32(&offset);
1067 const uint32_t exit_code = packet.GetU32(&offset);
1068 s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))",
1069 term_code, term_code, exit_code, exit_code);
1070 } break;
1071
1072 case KDP_REATTACH: {
1073 const uint16_t reply_port = ntohs(packet.GetU16(&offset));
1074 s.Printf(" (reply_port = %u)", reply_port);
1075 } break;
1076
1077 case KDP_READMSR64: {
1078 const uint32_t address = packet.GetU32(&offset);
1079 const uint16_t lcpu = packet.GetU16(&offset);
1080 s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu);
1081 } break;
1082
1083 case KDP_WRITEMSR64: {
1084 const uint32_t address = packet.GetU32(&offset);
1085 const uint16_t lcpu = packet.GetU16(&offset);
1086 const uint32_t nbytes = packet.GetByteSize() - offset;
1087 s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu,
1088 address, nbytes);
1089 if (nbytes > 0)
Jim Inghamc963f202017-03-04 01:15:24 +00001090 DumpDataExtractor(packet,
1091 &s, // Stream to dump to
1092 offset, // Offset within "packet"
1093 eFormatHex, // Format to use
1094 1, // Size of each item in
1095 // bytes
1096 nbytes, // Number of items
1097 16, // Number per line
1098 LLDB_INVALID_ADDRESS, // Don't show addresses
1099 // before each line
1100 0, 0); // No bitfields
Kate Stoneb9c1b512016-09-06 20:57:50 +00001101 } break;
1102
1103 case KDP_READIOPORT: {
1104 const uint16_t lcpu = packet.GetU16(&offset);
1105 const uint16_t address = packet.GetU16(&offset);
1106 const uint16_t nbytes = packet.GetU16(&offset);
1107 s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address,
1108 nbytes);
1109 } break;
1110
1111 case KDP_WRITEIOPORT: {
1112 const uint16_t lcpu = packet.GetU16(&offset);
1113 const uint16_t address = packet.GetU16(&offset);
1114 const uint16_t nbytes = packet.GetU16(&offset);
1115 s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu,
1116 address, nbytes);
1117 if (nbytes > 0)
Jim Inghamc963f202017-03-04 01:15:24 +00001118 DumpDataExtractor(packet,
1119 &s, // Stream to dump to
1120 offset, // Offset within "packet"
1121 eFormatHex, // Format to use
1122 1, // Size of each item in
1123 // bytes
1124 nbytes, // Number of items
1125 16, // Number per line
1126 LLDB_INVALID_ADDRESS, // Don't show addresses
1127 // before each line
1128 0, 0); // No bitfields
Kate Stoneb9c1b512016-09-06 20:57:50 +00001129 } break;
1130
1131 case KDP_DUMPINFO: {
1132 const uint32_t count = packet.GetByteSize() - offset;
1133 s.Printf(" (count = %u, bytes = \n", count);
1134 if (count > 0)
Jim Inghamc963f202017-03-04 01:15:24 +00001135 DumpDataExtractor(packet,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001136 &s, // Stream to dump to
1137 offset, // Offset within "packet"
1138 eFormatHex, // Format to use
1139 1, // Size of each item in bytes
1140 count, // Number of items
1141 16, // Number per line
1142 LLDB_INVALID_ADDRESS, // Don't show addresses before each line
1143 0, 0); // No bitfields
1144
1145 } break;
1146 }
1147 }
1148 } else {
1149 error_desc = "error: invalid packet command: ";
1150 }
1151 }
1152
1153 if (error_desc) {
1154 s.PutCString(error_desc);
1155
Jim Inghamc963f202017-03-04 01:15:24 +00001156 DumpDataExtractor(packet,
1157 &s, // Stream to dump to
1158 0, // Offset into "packet"
1159 eFormatBytes, // Dump as hex bytes
1160 1, // Size of each item is 1 for
1161 // single bytes
1162 packet.GetByteSize(), // Number of bytes
1163 UINT32_MAX, // Num bytes per line
1164 LLDB_INVALID_ADDRESS, // Base address
1165 0, 0); // Bitfield info set to not do
1166 // anything bitfield related
Kate Stoneb9c1b512016-09-06 20:57:50 +00001167 }
1168}
1169
1170uint32_t CommunicationKDP::SendRequestReadRegisters(uint32_t cpu,
1171 uint32_t flavor, void *dst,
1172 uint32_t dst_len,
Zachary Turner97206d52017-05-12 04:51:55 +00001173 Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001174 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
1175 m_byte_order);
1176 const CommandType command = KDP_READREGS;
1177 // Size is header + 4 byte cpu and 4 byte flavor
1178 const uint32_t command_length = 8 + 4 + 4;
1179 MakeRequestPacketHeader(command, request_packet, command_length);
1180 request_packet.PutHex32(cpu);
1181 request_packet.PutHex32(flavor);
1182 DataExtractor reply_packet;
1183 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
1184 lldb::offset_t offset = 8;
1185 uint32_t kdp_error = reply_packet.GetU32(&offset);
1186 uint32_t src_len = reply_packet.GetByteSize() - 12;
1187
1188 if (src_len > 0) {
1189 const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
1190 const void *src = reply_packet.GetData(&offset, bytes_to_copy);
1191 if (src) {
1192 ::memcpy(dst, src, bytes_to_copy);
1193 error.Clear();
Adrian Prantl05097242018-04-30 16:49:04 +00001194 // Return the number of bytes we could have returned regardless if we
1195 // copied them or not, just so we know when things don't match up
Kate Stoneb9c1b512016-09-06 20:57:50 +00001196 return src_len;
1197 }
1198 }
1199 if (kdp_error)
1200 error.SetErrorStringWithFormat(
1201 "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu,
1202 flavor, kdp_error);
1203 else
1204 error.SetErrorStringWithFormat(
1205 "failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
1206 } else {
1207 error.SetErrorString("failed to send packet");
1208 }
1209 return 0;
1210}
1211
1212uint32_t CommunicationKDP::SendRequestWriteRegisters(uint32_t cpu,
1213 uint32_t flavor,
1214 const void *src,
1215 uint32_t src_len,
Zachary Turner97206d52017-05-12 04:51:55 +00001216 Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001217 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
1218 m_byte_order);
1219 const CommandType command = KDP_WRITEREGS;
1220 // Size is header + 4 byte cpu and 4 byte flavor
1221 const uint32_t command_length = 8 + 4 + 4 + src_len;
1222 MakeRequestPacketHeader(command, request_packet, command_length);
1223 request_packet.PutHex32(cpu);
1224 request_packet.PutHex32(flavor);
1225 request_packet.Write(src, src_len);
1226 DataExtractor reply_packet;
1227 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
1228 lldb::offset_t offset = 8;
1229 uint32_t kdp_error = reply_packet.GetU32(&offset);
1230 if (kdp_error == 0)
1231 return src_len;
1232 error.SetErrorStringWithFormat(
1233 "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu,
1234 flavor, kdp_error);
1235 } else {
1236 error.SetErrorString("failed to send packet");
1237 }
1238 return 0;
1239}
1240
1241bool CommunicationKDP::SendRequestResume() {
1242 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
1243 m_byte_order);
1244 const CommandType command = KDP_RESUMECPUS;
1245 const uint32_t command_length = 12;
1246 MakeRequestPacketHeader(command, request_packet, command_length);
1247 request_packet.PutHex32(GetCPUMask());
1248
1249 DataExtractor reply_packet;
Jonas Devliegherea6682a42018-12-15 00:15:33 +00001250 return SendRequestAndGetReply(command, request_packet, reply_packet);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001251}
1252
1253bool CommunicationKDP::SendRequestBreakpoint(bool set, addr_t addr) {
1254 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
1255 m_byte_order);
1256 bool use_64 = (GetVersion() >= 11);
1257 uint32_t command_addr_byte_size = use_64 ? 8 : 4;
1258 const CommandType command =
1259 set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET)
1260 : (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE);
1261
1262 const uint32_t command_length = 8 + command_addr_byte_size;
1263 MakeRequestPacketHeader(command, request_packet, command_length);
1264 request_packet.PutMaxHex64(addr, command_addr_byte_size);
1265
1266 DataExtractor reply_packet;
1267 if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
1268 lldb::offset_t offset = 8;
1269 uint32_t kdp_error = reply_packet.GetU32(&offset);
1270 if (kdp_error == 0)
1271 return true;
1272 }
1273 return false;
1274}
1275
1276bool CommunicationKDP::SendRequestSuspend() {
1277 PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
1278 m_byte_order);
1279 const CommandType command = KDP_SUSPEND;
1280 const uint32_t command_length = 8;
1281 MakeRequestPacketHeader(command, request_packet, command_length);
1282 DataExtractor reply_packet;
Jonas Devliegherea6682a42018-12-15 00:15:33 +00001283 return SendRequestAndGetReply(command, request_packet, reply_packet);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001284}