diff options
author | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
---|---|---|
committer | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
commit | b9c1b51e45b845debb76d8658edabca70ca56079 (patch) | |
tree | dfcb5a13ef2b014202340f47036da383eaee74aa /lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp | |
parent | d5aa73376966339caad04013510626ec2e42c760 (diff) | |
download | bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.tar.gz bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.zip |
*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has
*** two obvious implications:
Firstly, merging this particular commit into a downstream fork may be a huge
effort. Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit. The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):
find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;
The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.
Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit. There are alternatives available that will attempt
to look through this change and find the appropriate prior commit. YMMV.
llvm-svn: 280751
Diffstat (limited to 'lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp | 2397 |
1 files changed, 1138 insertions, 1259 deletions
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp index bb0dfcfdb35..c016677674a 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "CommunicationKDP.h" // C Includes @@ -38,39 +37,26 @@ using namespace lldb_private; // CommunicationKDP constructor //---------------------------------------------------------------------- CommunicationKDP::CommunicationKDP(const char *comm_name) - : Communication(comm_name), - m_addr_byte_size(4), - m_byte_order(eByteOrderLittle), - m_packet_timeout(5), - m_sequence_mutex(), - m_is_running(false), - m_session_key(0u), - m_request_sequence_id(0u), - m_exception_sequence_id(0u), - m_kdp_version_version(0u), - m_kdp_version_feature(0u), - m_kdp_hostinfo_cpu_mask(0u), - m_kdp_hostinfo_cpu_type(0u), - m_kdp_hostinfo_cpu_subtype(0u) -{ -} + : Communication(comm_name), m_addr_byte_size(4), + m_byte_order(eByteOrderLittle), m_packet_timeout(5), m_sequence_mutex(), + m_is_running(false), m_session_key(0u), m_request_sequence_id(0u), + m_exception_sequence_id(0u), m_kdp_version_version(0u), + m_kdp_version_feature(0u), m_kdp_hostinfo_cpu_mask(0u), + m_kdp_hostinfo_cpu_type(0u), m_kdp_hostinfo_cpu_subtype(0u) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CommunicationKDP::~CommunicationKDP() -{ - if (IsConnected()) - { - Disconnect(); - } +CommunicationKDP::~CommunicationKDP() { + if (IsConnected()) { + Disconnect(); + } } -bool -CommunicationKDP::SendRequestPacket (const PacketStreamType &request_packet) -{ - std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); - return SendRequestPacketNoLock (request_packet); +bool CommunicationKDP::SendRequestPacket( + const PacketStreamType &request_packet) { + std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); + return SendRequestPacketNoLock(request_packet); } #if 0 @@ -82,408 +68,370 @@ typedef struct { } kdp_hdr_t; #endif -void -CommunicationKDP::MakeRequestPacketHeader (CommandType request_type, - PacketStreamType &request_packet, - uint16_t request_length) -{ - request_packet.Clear(); - request_packet.PutHex8 (request_type | ePacketTypeRequest); // Set the request type - request_packet.PutHex8 (m_request_sequence_id++); // Sequence number - request_packet.PutHex16 (request_length); // Length of the packet including this header - request_packet.PutHex32 (m_session_key); // Session key +void CommunicationKDP::MakeRequestPacketHeader(CommandType request_type, + PacketStreamType &request_packet, + uint16_t request_length) { + request_packet.Clear(); + request_packet.PutHex8(request_type | + ePacketTypeRequest); // Set the request type + request_packet.PutHex8(m_request_sequence_id++); // Sequence number + request_packet.PutHex16( + request_length); // Length of the packet including this header + request_packet.PutHex32(m_session_key); // Session key } -bool -CommunicationKDP::SendRequestAndGetReply (const CommandType command, - const PacketStreamType &request_packet, - DataExtractor &reply_packet) -{ - if (IsRunning()) - { - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); - if (log) - { - PacketStreamType log_strm; - DumpPacket (log_strm, request_packet.GetData(), request_packet.GetSize()); - log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); - } - return false; +bool CommunicationKDP::SendRequestAndGetReply( + const CommandType command, const PacketStreamType &request_packet, + DataExtractor &reply_packet) { + if (IsRunning()) { + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); + if (log) { + PacketStreamType log_strm; + DumpPacket(log_strm, request_packet.GetData(), request_packet.GetSize()); + log->Printf("error: kdp running, not sending packet: %.*s", + (uint32_t)log_strm.GetSize(), log_strm.GetData()); } + return false; + } - std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); + std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); #ifdef LLDB_CONFIGURATION_DEBUG - // NOTE: this only works for packets that are in native endian byte order - assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2))); + // NOTE: this only works for packets that are in native endian byte order + assert(request_packet.GetSize() == + *((uint16_t *)(request_packet.GetData() + 2))); #endif - lldb::offset_t offset = 1; - const uint32_t num_retries = 3; - for (uint32_t i=0; i<num_retries; ++i) - { - if (SendRequestPacketNoLock(request_packet)) - { - const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1]; - while (1) - { - if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ())) - { - offset = 0; - const uint8_t reply_command = reply_packet.GetU8 (&offset); - const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset); - if (request_sequence_id == reply_sequence_id) - { - // The sequent ID was correct, now verify we got the response we were looking for - if ((reply_command & eCommandTypeMask) == command) - { - // Success - if (command == KDP_RESUMECPUS) - m_is_running.SetValue(true, eBroadcastAlways); - return true; - } - else - { - // Failed to get the correct response, bail - reply_packet.Clear(); - return false; - } - } - else if (reply_sequence_id > request_sequence_id) - { - // Sequence ID was greater than the sequence ID of the packet we sent, something - // is really wrong... - reply_packet.Clear(); - return false; - } - else - { - // The reply sequence ID was less than our current packet's sequence ID - // so we should keep trying to get a response because this was a response - // for a previous packet that we must have retried. - } - } - else - { - // Break and retry sending the packet as we didn't get a response due to timeout - break; - } + lldb::offset_t offset = 1; + const uint32_t num_retries = 3; + for (uint32_t i = 0; i < num_retries; ++i) { + if (SendRequestPacketNoLock(request_packet)) { + const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1]; + while (1) { + if (WaitForPacketWithTimeoutMicroSecondsNoLock( + reply_packet, GetPacketTimeoutInMicroSeconds())) { + offset = 0; + const uint8_t reply_command = reply_packet.GetU8(&offset); + const uint8_t reply_sequence_id = reply_packet.GetU8(&offset); + if (request_sequence_id == reply_sequence_id) { + // The sequent ID was correct, now verify we got the response we + // were looking for + if ((reply_command & eCommandTypeMask) == command) { + // Success + if (command == KDP_RESUMECPUS) + m_is_running.SetValue(true, eBroadcastAlways); + return true; + } else { + // Failed to get the correct response, bail + reply_packet.Clear(); + return false; } + } else if (reply_sequence_id > request_sequence_id) { + // Sequence ID was greater than the sequence ID of the packet we + // sent, something + // is really wrong... + reply_packet.Clear(); + return false; + } else { + // The reply sequence ID was less than our current packet's sequence + // ID + // so we should keep trying to get a response because this was a + // response + // for a previous packet that we must have retried. + } + } else { + // Break and retry sending the packet as we didn't get a response due + // to timeout + break; } + } } - reply_packet.Clear(); - return false; + } + reply_packet.Clear(); + return false; } -bool -CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packet) -{ - if (IsConnected()) - { - const char *packet_data = request_packet.GetData(); - const size_t packet_size = request_packet.GetSize(); - - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); - if (log) - { - PacketStreamType log_strm; - DumpPacket (log_strm, packet_data, packet_size); - log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); - } - ConnectionStatus status = eConnectionStatusSuccess; - - size_t bytes_written = Write (packet_data, - packet_size, - status, - NULL); - - if (bytes_written == packet_size) - return true; - - if (log) - log->Printf ("error: failed to send packet entire packet %" PRIu64 " of %" PRIu64 " bytes sent", (uint64_t)bytes_written, (uint64_t)packet_size); +bool CommunicationKDP::SendRequestPacketNoLock( + const PacketStreamType &request_packet) { + if (IsConnected()) { + const char *packet_data = request_packet.GetData(); + const size_t packet_size = request_packet.GetSize(); + + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); + if (log) { + PacketStreamType log_strm; + DumpPacket(log_strm, packet_data, packet_size); + log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } - return false; -} + ConnectionStatus status = eConnectionStatusSuccess; -bool -CommunicationKDP::GetSequenceMutex(std::unique_lock<std::recursive_mutex> &lock) -{ - return (lock = std::unique_lock<std::recursive_mutex>(m_sequence_mutex, std::try_to_lock)).owns_lock(); + size_t bytes_written = Write(packet_data, packet_size, status, NULL); + + if (bytes_written == packet_size) + return true; + + if (log) + log->Printf("error: failed to send packet entire packet %" PRIu64 + " of %" PRIu64 " bytes sent", + (uint64_t)bytes_written, (uint64_t)packet_size); + } + return false; } -bool -CommunicationKDP::WaitForNotRunningPrivate(const std::chrono::microseconds &timeout) -{ - return m_is_running.WaitForValueEqualTo(false, timeout, NULL); +bool CommunicationKDP::GetSequenceMutex( + std::unique_lock<std::recursive_mutex> &lock) { + return (lock = std::unique_lock<std::recursive_mutex>(m_sequence_mutex, + std::try_to_lock)) + .owns_lock(); } -size_t -CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &packet, uint32_t timeout_usec) -{ - std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); - return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec); +bool CommunicationKDP::WaitForNotRunningPrivate( + const std::chrono::microseconds &timeout) { + return m_is_running.WaitForValueEqualTo(false, timeout, NULL); } size_t -CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec) -{ - uint8_t buffer[8192]; - Error error; - - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE)); +CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds(DataExtractor &packet, + uint32_t timeout_usec) { + std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); + return WaitForPacketWithTimeoutMicroSecondsNoLock(packet, timeout_usec); +} - // Check for a packet from our cache first without trying any reading... - if (CheckForPacket (NULL, 0, packet)) +size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock( + DataExtractor &packet, uint32_t timeout_usec) { + uint8_t buffer[8192]; + Error error; + + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS | + KDP_LOG_VERBOSE)); + + // Check for a packet from our cache first without trying any reading... + if (CheckForPacket(NULL, 0, packet)) + return packet.GetByteSize(); + + bool timed_out = false; + while (IsConnected() && !timed_out) { + lldb::ConnectionStatus status = eConnectionStatusNoConnection; + size_t bytes_read = + Read(buffer, sizeof(buffer), timeout_usec, status, &error); + + if (log) + log->Printf("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, " + "status = %s, error = %s) => bytes_read = %" PRIu64, + LLVM_PRETTY_FUNCTION, timeout_usec, + Communication::ConnectionStatusAsCString(status), + error.AsCString(), (uint64_t)bytes_read); + + if (bytes_read > 0) { + if (CheckForPacket(buffer, bytes_read, packet)) return packet.GetByteSize(); - - bool timed_out = false; - while (IsConnected() && !timed_out) - { - lldb::ConnectionStatus status = eConnectionStatusNoConnection; - size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); - - if (log) - log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64, - LLVM_PRETTY_FUNCTION, - timeout_usec, - Communication::ConnectionStatusAsCString (status), - error.AsCString(), - (uint64_t)bytes_read); - - if (bytes_read > 0) - { - if (CheckForPacket (buffer, bytes_read, packet)) - return packet.GetByteSize(); - } - else - { - switch (status) - { - case eConnectionStatusInterrupted: - case eConnectionStatusTimedOut: - timed_out = true; - break; - case eConnectionStatusSuccess: - //printf ("status = success but error = %s\n", error.AsCString("<invalid>")); - break; - - case eConnectionStatusEndOfFile: - case eConnectionStatusNoConnection: - case eConnectionStatusLostConnection: - case eConnectionStatusError: - Disconnect(); - break; - } - } + } else { + switch (status) { + case eConnectionStatusInterrupted: + case eConnectionStatusTimedOut: + timed_out = true; + break; + case eConnectionStatusSuccess: + // printf ("status = success but error = %s\n", + // error.AsCString("<invalid>")); + break; + + case eConnectionStatusEndOfFile: + case eConnectionStatusNoConnection: + case eConnectionStatusLostConnection: + case eConnectionStatusError: + Disconnect(); + break; + } } - packet.Clear (); - return 0; + } + packet.Clear(); + return 0; } -bool -CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet) -{ - // Put the packet data into the buffer in a thread safe fashion - std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); +bool CommunicationKDP::CheckForPacket(const uint8_t *src, size_t src_len, + DataExtractor &packet) { + // Put the packet data into the buffer in a thread safe fashion + std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); - Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); - if (src && src_len > 0) - { - if (log && log->GetVerbose()) - { - PacketStreamType log_strm; - DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS); - log->Printf ("CommunicationKDP::%s adding %u bytes: %s", - __FUNCTION__, - (uint32_t)src_len, - log_strm.GetData()); - } - m_bytes.append ((const char *)src, src_len); + if (src && src_len > 0) { + if (log && log->GetVerbose()) { + PacketStreamType log_strm; + DataExtractor::DumpHexBytes(&log_strm, src, src_len, UINT32_MAX, + LLDB_INVALID_ADDRESS); + log->Printf("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__, + (uint32_t)src_len, log_strm.GetData()); } - - // Make sure we at least have enough bytes for a packet header - const size_t bytes_available = m_bytes.size(); - if (bytes_available >= 8) - { - packet.SetData (&m_bytes[0], bytes_available, m_byte_order); - lldb::offset_t offset = 0; - uint8_t reply_command = packet.GetU8(&offset); - switch (reply_command) - { - case ePacketTypeRequest | KDP_EXCEPTION: - case ePacketTypeRequest | KDP_TERMINATION: - // We got an exception request, so be sure to send an ACK - { - PacketStreamType request_ack_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - // Set the reply but and make the ACK packet - request_ack_packet.PutHex8 (reply_command | ePacketTypeReply); - request_ack_packet.PutHex8 (packet.GetU8(&offset)); - request_ack_packet.PutHex16 (packet.GetU16(&offset)); - request_ack_packet.PutHex32 (packet.GetU32(&offset)); - m_is_running.SetValue(false, eBroadcastAlways); - // Ack to the exception or termination - SendRequestPacketNoLock (request_ack_packet); - } - // Fall through to case below to get packet contents - LLVM_FALLTHROUGH; - case ePacketTypeReply | KDP_CONNECT: - case ePacketTypeReply | KDP_DISCONNECT: - case ePacketTypeReply | KDP_HOSTINFO: - case ePacketTypeReply | KDP_VERSION: - case ePacketTypeReply | KDP_MAXBYTES: - case ePacketTypeReply | KDP_READMEM: - case ePacketTypeReply | KDP_WRITEMEM: - case ePacketTypeReply | KDP_READREGS: - case ePacketTypeReply | KDP_WRITEREGS: - case ePacketTypeReply | KDP_LOAD: - case ePacketTypeReply | KDP_IMAGEPATH: - case ePacketTypeReply | KDP_SUSPEND: - case ePacketTypeReply | KDP_RESUMECPUS: - case ePacketTypeReply | KDP_BREAKPOINT_SET: - case ePacketTypeReply | KDP_BREAKPOINT_REMOVE: - case ePacketTypeReply | KDP_REGIONS: - case ePacketTypeReply | KDP_REATTACH: - case ePacketTypeReply | KDP_HOSTREBOOT: - case ePacketTypeReply | KDP_READMEM64: - case ePacketTypeReply | KDP_WRITEMEM64: - case ePacketTypeReply | KDP_BREAKPOINT_SET64: - case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64: - case ePacketTypeReply | KDP_KERNELVERSION: - case ePacketTypeReply | KDP_READPHYSMEM64: - case ePacketTypeReply | KDP_WRITEPHYSMEM64: - case ePacketTypeReply | KDP_READIOPORT: - case ePacketTypeReply | KDP_WRITEIOPORT: - case ePacketTypeReply | KDP_READMSR64: - case ePacketTypeReply | KDP_WRITEMSR64: - case ePacketTypeReply | KDP_DUMPINFO: - { - offset = 2; - const uint16_t length = packet.GetU16 (&offset); - if (length <= bytes_available) - { - // We have an entire packet ready, we need to copy the data - // bytes into a buffer that will be owned by the packet and - // erase the bytes from our communcation buffer "m_bytes" - packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length))); - m_bytes.erase (0, length); - - if (log) - { - PacketStreamType log_strm; - DumpPacket (log_strm, packet); - - log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); - } - return true; - } - } - break; - - default: - // Unrecognized reply command byte, erase this byte and try to get back on track - if (log) - log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x", - __FUNCTION__, - (uint8_t)m_bytes[0]); - m_bytes.erase(0, 1); - break; + m_bytes.append((const char *)src, src_len); + } + + // Make sure we at least have enough bytes for a packet header + const size_t bytes_available = m_bytes.size(); + if (bytes_available >= 8) { + packet.SetData(&m_bytes[0], bytes_available, m_byte_order); + lldb::offset_t offset = 0; + uint8_t reply_command = packet.GetU8(&offset); + switch (reply_command) { + case ePacketTypeRequest | KDP_EXCEPTION: + case ePacketTypeRequest | KDP_TERMINATION: + // We got an exception request, so be sure to send an ACK + { + PacketStreamType request_ack_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + // Set the reply but and make the ACK packet + request_ack_packet.PutHex8(reply_command | ePacketTypeReply); + request_ack_packet.PutHex8(packet.GetU8(&offset)); + request_ack_packet.PutHex16(packet.GetU16(&offset)); + request_ack_packet.PutHex32(packet.GetU32(&offset)); + m_is_running.SetValue(false, eBroadcastAlways); + // Ack to the exception or termination + SendRequestPacketNoLock(request_ack_packet); + } + // Fall through to case below to get packet contents + LLVM_FALLTHROUGH; + case ePacketTypeReply | KDP_CONNECT: + case ePacketTypeReply | KDP_DISCONNECT: + case ePacketTypeReply | KDP_HOSTINFO: + case ePacketTypeReply | KDP_VERSION: + case ePacketTypeReply | KDP_MAXBYTES: + case ePacketTypeReply | KDP_READMEM: + case ePacketTypeReply | KDP_WRITEMEM: + case ePacketTypeReply | KDP_READREGS: + case ePacketTypeReply | KDP_WRITEREGS: + case ePacketTypeReply | KDP_LOAD: + case ePacketTypeReply | KDP_IMAGEPATH: + case ePacketTypeReply | KDP_SUSPEND: + case ePacketTypeReply | KDP_RESUMECPUS: + case ePacketTypeReply | KDP_BREAKPOINT_SET: + case ePacketTypeReply | KDP_BREAKPOINT_REMOVE: + case ePacketTypeReply | KDP_REGIONS: + case ePacketTypeReply | KDP_REATTACH: + case ePacketTypeReply | KDP_HOSTREBOOT: + case ePacketTypeReply | KDP_READMEM64: + case ePacketTypeReply | KDP_WRITEMEM64: + case ePacketTypeReply | KDP_BREAKPOINT_SET64: + case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64: + case ePacketTypeReply | KDP_KERNELVERSION: + case ePacketTypeReply | KDP_READPHYSMEM64: + case ePacketTypeReply | KDP_WRITEPHYSMEM64: + case ePacketTypeReply | KDP_READIOPORT: + case ePacketTypeReply | KDP_WRITEIOPORT: + case ePacketTypeReply | KDP_READMSR64: + case ePacketTypeReply | KDP_WRITEMSR64: + case ePacketTypeReply | KDP_DUMPINFO: { + offset = 2; + const uint16_t length = packet.GetU16(&offset); + if (length <= bytes_available) { + // We have an entire packet ready, we need to copy the data + // bytes into a buffer that will be owned by the packet and + // erase the bytes from our communcation buffer "m_bytes" + packet.SetData(DataBufferSP(new DataBufferHeap(&m_bytes[0], length))); + m_bytes.erase(0, length); + + if (log) { + PacketStreamType log_strm; + DumpPacket(log_strm, packet); + + log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } + return true; + } + } break; + + default: + // Unrecognized reply command byte, erase this byte and try to get back on + // track + if (log) + log->Printf("CommunicationKDP::%s: tossing junk byte: 0x%2.2x", + __FUNCTION__, (uint8_t)m_bytes[0]); + m_bytes.erase(0, 1); + break; } - packet.Clear(); - return false; + } + packet.Clear(); + return false; } - -bool -CommunicationKDP::SendRequestConnect (uint16_t reply_port, - uint16_t exc_port, - const char *greeting) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - if (greeting == NULL) - greeting = ""; - - const CommandType command = KDP_CONNECT; - // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL - const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1; - MakeRequestPacketHeader (command, request_packet, command_length); - // Always send connect ports as little endian - request_packet.SetByteOrder (eByteOrderLittle); - request_packet.PutHex16 (htons(reply_port)); - request_packet.PutHex16 (htons(exc_port)); - request_packet.SetByteOrder (m_byte_order); - request_packet.PutCString (greeting); - DataExtractor reply_packet; - return SendRequestAndGetReply (command, request_packet, reply_packet); +bool CommunicationKDP::SendRequestConnect(uint16_t reply_port, + uint16_t exc_port, + const char *greeting) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + if (greeting == NULL) + greeting = ""; + + const CommandType command = KDP_CONNECT; + // Length is 82 uint16_t and the length of the greeting C string with the + // terminating NULL + const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1; + MakeRequestPacketHeader(command, request_packet, command_length); + // Always send connect ports as little endian + request_packet.SetByteOrder(eByteOrderLittle); + request_packet.PutHex16(htons(reply_port)); + request_packet.PutHex16(htons(exc_port)); + request_packet.SetByteOrder(m_byte_order); + request_packet.PutCString(greeting); + DataExtractor reply_packet; + return SendRequestAndGetReply(command, request_packet, reply_packet); } -void -CommunicationKDP::ClearKDPSettings () -{ - m_request_sequence_id = 0; - m_kdp_version_version = 0; - m_kdp_version_feature = 0; - m_kdp_hostinfo_cpu_mask = 0; - m_kdp_hostinfo_cpu_type = 0; - m_kdp_hostinfo_cpu_subtype = 0; +void CommunicationKDP::ClearKDPSettings() { + m_request_sequence_id = 0; + m_kdp_version_version = 0; + m_kdp_version_feature = 0; + m_kdp_hostinfo_cpu_mask = 0; + m_kdp_hostinfo_cpu_type = 0; + m_kdp_hostinfo_cpu_subtype = 0; } -bool -CommunicationKDP::SendRequestReattach (uint16_t reply_port) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_REATTACH; - // Length is 8 bytes for the header plus 2 bytes for the reply UDP port - const uint32_t command_length = 8 + 2; - MakeRequestPacketHeader (command, request_packet, command_length); - // Always send connect ports as little endian - request_packet.SetByteOrder (eByteOrderLittle); - request_packet.PutHex16(htons(reply_port)); - request_packet.SetByteOrder (m_byte_order); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - // Reset the sequence ID to zero for reattach - ClearKDPSettings (); - lldb::offset_t offset = 4; - m_session_key = reply_packet.GetU32 (&offset); - return true; - } - return false; +bool CommunicationKDP::SendRequestReattach(uint16_t reply_port) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_REATTACH; + // Length is 8 bytes for the header plus 2 bytes for the reply UDP port + const uint32_t command_length = 8 + 2; + MakeRequestPacketHeader(command, request_packet, command_length); + // Always send connect ports as little endian + request_packet.SetByteOrder(eByteOrderLittle); + request_packet.PutHex16(htons(reply_port)); + request_packet.SetByteOrder(m_byte_order); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + // Reset the sequence ID to zero for reattach + ClearKDPSettings(); + lldb::offset_t offset = 4; + m_session_key = reply_packet.GetU32(&offset); + return true; + } + return false; } -uint32_t -CommunicationKDP::GetVersion () -{ - if (!VersionIsValid()) - SendRequestVersion(); - return m_kdp_version_version; +uint32_t CommunicationKDP::GetVersion() { + if (!VersionIsValid()) + SendRequestVersion(); + return m_kdp_version_version; } -uint32_t -CommunicationKDP::GetFeatureFlags () -{ - if (!VersionIsValid()) - SendRequestVersion(); - return m_kdp_version_feature; +uint32_t CommunicationKDP::GetFeatureFlags() { + if (!VersionIsValid()) + SendRequestVersion(); + return m_kdp_version_feature; } -bool -CommunicationKDP::SendRequestVersion () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_VERSION; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - m_kdp_version_version = reply_packet.GetU32 (&offset); - m_kdp_version_feature = reply_packet.GetU32 (&offset); - return true; - } - return false; +bool CommunicationKDP::SendRequestVersion() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_VERSION; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + m_kdp_version_version = reply_packet.GetU32(&offset); + m_kdp_version_feature = reply_packet.GetU32(&offset); + return true; + } + return false; } #if 0 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... @@ -514,932 +462,863 @@ CommunicationKDP::SendRequestImagePath () } #endif -uint32_t -CommunicationKDP::GetCPUMask () -{ - if (!HostInfoIsValid()) - SendRequestHostInfo(); - return m_kdp_hostinfo_cpu_mask; +uint32_t CommunicationKDP::GetCPUMask() { + if (!HostInfoIsValid()) + SendRequestHostInfo(); + return m_kdp_hostinfo_cpu_mask; } -uint32_t -CommunicationKDP::GetCPUType () -{ - if (!HostInfoIsValid()) - SendRequestHostInfo(); - return m_kdp_hostinfo_cpu_type; +uint32_t CommunicationKDP::GetCPUType() { + if (!HostInfoIsValid()) + SendRequestHostInfo(); + return m_kdp_hostinfo_cpu_type; } -uint32_t -CommunicationKDP::GetCPUSubtype () -{ - if (!HostInfoIsValid()) - SendRequestHostInfo(); - return m_kdp_hostinfo_cpu_subtype; +uint32_t CommunicationKDP::GetCPUSubtype() { + if (!HostInfoIsValid()) + SendRequestHostInfo(); + return m_kdp_hostinfo_cpu_subtype; } -lldb_private::UUID -CommunicationKDP::GetUUID () -{ - UUID uuid; - if (GetKernelVersion() == NULL) - return uuid; - - if (m_kernel_version.find("UUID=") == std::string::npos) - return uuid; - - size_t p = m_kernel_version.find("UUID=") + strlen ("UUID="); - std::string uuid_str = m_kernel_version.substr(p, 36); - if (uuid_str.size() < 32) - return uuid; +lldb_private::UUID CommunicationKDP::GetUUID() { + UUID uuid; + if (GetKernelVersion() == NULL) + return uuid; - if (uuid.SetFromCString (uuid_str.c_str()) == 0) - { - UUID invalid_uuid; - return invalid_uuid; - } + if (m_kernel_version.find("UUID=") == std::string::npos) + return uuid; + size_t p = m_kernel_version.find("UUID=") + strlen("UUID="); + std::string uuid_str = m_kernel_version.substr(p, 36); + if (uuid_str.size() < 32) return uuid; -} -bool -CommunicationKDP::RemoteIsEFI () -{ - if (GetKernelVersion() == NULL) - return false; - if (strncmp (m_kernel_version.c_str(), "EFI", 3) == 0) - return true; - else - return false; -} + if (uuid.SetFromCString(uuid_str.c_str()) == 0) { + UUID invalid_uuid; + return invalid_uuid; + } -bool -CommunicationKDP::RemoteIsDarwinKernel () -{ - if (GetKernelVersion() == NULL) - return false; - if (m_kernel_version.find("Darwin Kernel") != std::string::npos) - return true; - else - return false; + return uuid; } -lldb::addr_t -CommunicationKDP::GetLoadAddress () -{ - if (GetKernelVersion() == NULL) - return LLDB_INVALID_ADDRESS; - - if (m_kernel_version.find("stext=") == std::string::npos) - return LLDB_INVALID_ADDRESS; - size_t p = m_kernel_version.find("stext=") + strlen ("stext="); - if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x') - return LLDB_INVALID_ADDRESS; - - addr_t kernel_load_address; - errno = 0; - kernel_load_address = ::strtoul (m_kernel_version.c_str() + p, NULL, 16); - if (errno != 0 || kernel_load_address == 0) - return LLDB_INVALID_ADDRESS; - - return kernel_load_address; +bool CommunicationKDP::RemoteIsEFI() { + if (GetKernelVersion() == NULL) + return false; + if (strncmp(m_kernel_version.c_str(), "EFI", 3) == 0) + return true; + else + return false; } -bool -CommunicationKDP::SendRequestHostInfo () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_HOSTINFO; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset); - m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset); - m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset); - - ArchSpec kernel_arch; - kernel_arch.SetArchitecture (eArchTypeMachO, - m_kdp_hostinfo_cpu_type, - m_kdp_hostinfo_cpu_subtype); - - m_addr_byte_size = kernel_arch.GetAddressByteSize(); - m_byte_order = kernel_arch.GetByteOrder(); - return true; - } +bool CommunicationKDP::RemoteIsDarwinKernel() { + if (GetKernelVersion() == NULL) + return false; + if (m_kernel_version.find("Darwin Kernel") != std::string::npos) + return true; + else return false; } -const char * -CommunicationKDP::GetKernelVersion () -{ - if (m_kernel_version.empty()) - SendRequestKernelVersion (); - return m_kernel_version.c_str(); -} +lldb::addr_t CommunicationKDP::GetLoadAddress() { + if (GetKernelVersion() == NULL) + return LLDB_INVALID_ADDRESS; -bool -CommunicationKDP::SendRequestKernelVersion () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_KERNELVERSION; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - const char *kernel_version_cstr = reply_packet.PeekCStr(8); - if (kernel_version_cstr && kernel_version_cstr[0]) - m_kernel_version.assign (kernel_version_cstr); - return true; - } - return false; + if (m_kernel_version.find("stext=") == std::string::npos) + return LLDB_INVALID_ADDRESS; + size_t p = m_kernel_version.find("stext=") + strlen("stext="); + if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x') + return LLDB_INVALID_ADDRESS; + + addr_t kernel_load_address; + errno = 0; + kernel_load_address = ::strtoul(m_kernel_version.c_str() + p, NULL, 16); + if (errno != 0 || kernel_load_address == 0) + return LLDB_INVALID_ADDRESS; + + return kernel_load_address; } -bool -CommunicationKDP::SendRequestDisconnect () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_DISCONNECT; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - // Are we supposed to get a reply for disconnect? - } - ClearKDPSettings (); +bool CommunicationKDP::SendRequestHostInfo() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_HOSTINFO; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + m_kdp_hostinfo_cpu_mask = reply_packet.GetU32(&offset); + m_kdp_hostinfo_cpu_type = reply_packet.GetU32(&offset); + m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32(&offset); + + ArchSpec kernel_arch; + kernel_arch.SetArchitecture(eArchTypeMachO, m_kdp_hostinfo_cpu_type, + m_kdp_hostinfo_cpu_subtype); + + m_addr_byte_size = kernel_arch.GetAddressByteSize(); + m_byte_order = kernel_arch.GetByteOrder(); return true; + } + return false; } -uint32_t -CommunicationKDP::SendRequestReadMemory (lldb::addr_t addr, - void *dst, - uint32_t dst_len, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - bool use_64 = (GetVersion() >= 11); - uint32_t command_addr_byte_size = use_64 ? 8 : 4; - const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM; - // Size is header + address size + uint32_t length - const uint32_t command_length = 8 + command_addr_byte_size + 4; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutMaxHex64 (addr, command_addr_byte_size); - request_packet.PutHex32 (dst_len); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - uint32_t src_len = reply_packet.GetByteSize() - 12; - - if (src_len > 0) - { - const void *src = reply_packet.GetData(&offset, src_len); - if (src) - { - ::memcpy (dst, src, src_len); - error.Clear(); - return src_len; - } - } - if (kdp_error) - error.SetErrorStringWithFormat ("kdp read memory failed (error %u)", kdp_error); - else - error.SetErrorString ("kdp read memory failed"); - } - else - { - error.SetErrorString ("failed to send packet"); - } - return 0; +const char *CommunicationKDP::GetKernelVersion() { + if (m_kernel_version.empty()) + SendRequestKernelVersion(); + return m_kernel_version.c_str(); } +bool CommunicationKDP::SendRequestKernelVersion() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_KERNELVERSION; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + const char *kernel_version_cstr = reply_packet.PeekCStr(8); + if (kernel_version_cstr && kernel_version_cstr[0]) + m_kernel_version.assign(kernel_version_cstr); + return true; + } + return false; +} -uint32_t -CommunicationKDP::SendRequestWriteMemory (lldb::addr_t addr, - const void *src, - uint32_t src_len, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - bool use_64 = (GetVersion() >= 11); - uint32_t command_addr_byte_size = use_64 ? 8 : 4; - const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM; - // Size is header + address size + uint32_t length - const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutMaxHex64 (addr, command_addr_byte_size); - request_packet.PutHex32 (src_len); - request_packet.PutRawBytes(src, src_len); +bool CommunicationKDP::SendRequestDisconnect() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_DISCONNECT; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + // Are we supposed to get a reply for disconnect? + } + ClearKDPSettings(); + return true; +} - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - if (kdp_error) - error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error); - else - { - error.Clear(); - return src_len; - } +uint32_t CommunicationKDP::SendRequestReadMemory(lldb::addr_t addr, void *dst, + uint32_t dst_len, + Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + bool use_64 = (GetVersion() >= 11); + uint32_t command_addr_byte_size = use_64 ? 8 : 4; + const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM; + // Size is header + address size + uint32_t length + const uint32_t command_length = 8 + command_addr_byte_size + 4; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutMaxHex64(addr, command_addr_byte_size); + request_packet.PutHex32(dst_len); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + uint32_t src_len = reply_packet.GetByteSize() - 12; + + if (src_len > 0) { + const void *src = reply_packet.GetData(&offset, src_len); + if (src) { + ::memcpy(dst, src, src_len); + error.Clear(); + return src_len; + } } + if (kdp_error) + error.SetErrorStringWithFormat("kdp read memory failed (error %u)", + kdp_error); else - { - error.SetErrorString ("failed to send packet"); - } - return 0; + error.SetErrorString("kdp read memory failed"); + } else { + error.SetErrorString("failed to send packet"); + } + return 0; } -bool -CommunicationKDP::SendRawRequest (uint8_t command_byte, - const void *src, // Raw packet payload bytes - uint32_t src_len, // Raw packet payload length - DataExtractor &reply_packet, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - // Size is header + address size + uint32_t length - const uint32_t command_length = 8 + src_len; - const CommandType command = (CommandType)command_byte; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutRawBytes(src, src_len); - - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - if (kdp_error && (command_byte != KDP_DUMPINFO)) - error.SetErrorStringWithFormat ("request packet 0x%8.8x failed (error %u)", command_byte, kdp_error); - else - { - error.Clear(); - return true; - } - } - else - { - error.SetErrorString ("failed to send packet"); +uint32_t CommunicationKDP::SendRequestWriteMemory(lldb::addr_t addr, + const void *src, + uint32_t src_len, + Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + bool use_64 = (GetVersion() >= 11); + uint32_t command_addr_byte_size = use_64 ? 8 : 4; + const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM; + // Size is header + address size + uint32_t length + const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutMaxHex64(addr, command_addr_byte_size); + request_packet.PutHex32(src_len); + request_packet.PutRawBytes(src, src_len); + + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + if (kdp_error) + error.SetErrorStringWithFormat("kdp write memory failed (error %u)", + kdp_error); + else { + error.Clear(); + return src_len; } - return false; + } else { + error.SetErrorString("failed to send packet"); + } + return 0; } - -const char * -CommunicationKDP::GetCommandAsCString (uint8_t command) -{ - switch (command) - { - case KDP_CONNECT: return "KDP_CONNECT"; - case KDP_DISCONNECT: return "KDP_DISCONNECT"; - case KDP_HOSTINFO: return "KDP_HOSTINFO"; - case KDP_VERSION: return "KDP_VERSION"; - case KDP_MAXBYTES: return "KDP_MAXBYTES"; - case KDP_READMEM: return "KDP_READMEM"; - case KDP_WRITEMEM: return "KDP_WRITEMEM"; - case KDP_READREGS: return "KDP_READREGS"; - case KDP_WRITEREGS: return "KDP_WRITEREGS"; - case KDP_LOAD: return "KDP_LOAD"; - case KDP_IMAGEPATH: return "KDP_IMAGEPATH"; - case KDP_SUSPEND: return "KDP_SUSPEND"; - case KDP_RESUMECPUS: return "KDP_RESUMECPUS"; - case KDP_EXCEPTION: return "KDP_EXCEPTION"; - case KDP_TERMINATION: return "KDP_TERMINATION"; - case KDP_BREAKPOINT_SET: return "KDP_BREAKPOINT_SET"; - case KDP_BREAKPOINT_REMOVE: return "KDP_BREAKPOINT_REMOVE"; - case KDP_REGIONS: return "KDP_REGIONS"; - case KDP_REATTACH: return "KDP_REATTACH"; - case KDP_HOSTREBOOT: return "KDP_HOSTREBOOT"; - case KDP_READMEM64: return "KDP_READMEM64"; - case KDP_WRITEMEM64: return "KDP_WRITEMEM64"; - case KDP_BREAKPOINT_SET64: return "KDP_BREAKPOINT64_SET"; - case KDP_BREAKPOINT_REMOVE64: return "KDP_BREAKPOINT64_REMOVE"; - case KDP_KERNELVERSION: return "KDP_KERNELVERSION"; - case KDP_READPHYSMEM64: return "KDP_READPHYSMEM64"; - case KDP_WRITEPHYSMEM64: return "KDP_WRITEPHYSMEM64"; - case KDP_READIOPORT: return "KDP_READIOPORT"; - case KDP_WRITEIOPORT: return "KDP_WRITEIOPORT"; - case KDP_READMSR64: return "KDP_READMSR64"; - case KDP_WRITEMSR64: return "KDP_WRITEMSR64"; - case KDP_DUMPINFO: return "KDP_DUMPINFO"; +bool CommunicationKDP::SendRawRequest( + uint8_t command_byte, + const void *src, // Raw packet payload bytes + uint32_t src_len, // Raw packet payload length + DataExtractor &reply_packet, Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + // Size is header + address size + uint32_t length + const uint32_t command_length = 8 + src_len; + const CommandType command = (CommandType)command_byte; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutRawBytes(src, src_len); + + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + if (kdp_error && (command_byte != KDP_DUMPINFO)) + error.SetErrorStringWithFormat("request packet 0x%8.8x failed (error %u)", + command_byte, kdp_error); + else { + error.Clear(); + return true; } - return NULL; + } else { + error.SetErrorString("failed to send packet"); + } + return false; } -void -CommunicationKDP::DumpPacket (Stream &s, const void *data, uint32_t data_len) -{ - DataExtractor extractor (data, data_len, m_byte_order, m_addr_byte_size); - DumpPacket (s, extractor); +const char *CommunicationKDP::GetCommandAsCString(uint8_t command) { + switch (command) { + case KDP_CONNECT: + return "KDP_CONNECT"; + case KDP_DISCONNECT: + return "KDP_DISCONNECT"; + case KDP_HOSTINFO: + return "KDP_HOSTINFO"; + case KDP_VERSION: + return "KDP_VERSION"; + case KDP_MAXBYTES: + return "KDP_MAXBYTES"; + case KDP_READMEM: + return "KDP_READMEM"; + case KDP_WRITEMEM: + return "KDP_WRITEMEM"; + case KDP_READREGS: + return "KDP_READREGS"; + case KDP_WRITEREGS: + return "KDP_WRITEREGS"; + case KDP_LOAD: + return "KDP_LOAD"; + case KDP_IMAGEPATH: + return "KDP_IMAGEPATH"; + case KDP_SUSPEND: + return "KDP_SUSPEND"; + case KDP_RESUMECPUS: + return "KDP_RESUMECPUS"; + case KDP_EXCEPTION: + return "KDP_EXCEPTION"; + case KDP_TERMINATION: + return "KDP_TERMINATION"; + case KDP_BREAKPOINT_SET: + return "KDP_BREAKPOINT_SET"; + case KDP_BREAKPOINT_REMOVE: + return "KDP_BREAKPOINT_REMOVE"; + case KDP_REGIONS: + return "KDP_REGIONS"; + case KDP_REATTACH: + return "KDP_REATTACH"; + case KDP_HOSTREBOOT: + return "KDP_HOSTREBOOT"; + case KDP_READMEM64: + return "KDP_READMEM64"; + case KDP_WRITEMEM64: + return "KDP_WRITEMEM64"; + case KDP_BREAKPOINT_SET64: + return "KDP_BREAKPOINT64_SET"; + case KDP_BREAKPOINT_REMOVE64: + return "KDP_BREAKPOINT64_REMOVE"; + case KDP_KERNELVERSION: + return "KDP_KERNELVERSION"; + case KDP_READPHYSMEM64: + return "KDP_READPHYSMEM64"; + case KDP_WRITEPHYSMEM64: + return "KDP_WRITEPHYSMEM64"; + case KDP_READIOPORT: + return "KDP_READIOPORT"; + case KDP_WRITEIOPORT: + return "KDP_WRITEIOPORT"; + case KDP_READMSR64: + return "KDP_READMSR64"; + case KDP_WRITEMSR64: + return "KDP_WRITEMSR64"; + case KDP_DUMPINFO: + return "KDP_DUMPINFO"; + } + return NULL; } -void -CommunicationKDP::DumpPacket (Stream &s, const DataExtractor& packet) -{ - const char *error_desc = NULL; - if (packet.GetByteSize() < 8) - { - error_desc = "error: invalid packet (too short): "; - } - else - { - lldb::offset_t offset = 0; - const uint8_t first_packet_byte = packet.GetU8 (&offset); - const uint8_t sequence_id = packet.GetU8 (&offset); - const uint16_t length = packet.GetU16 (&offset); - const uint32_t key = packet.GetU32 (&offset); - const CommandType command = ExtractCommand (first_packet_byte); - const char *command_name = GetCommandAsCString (command); - if (command_name) - { - const bool is_reply = ExtractIsReply(first_packet_byte); - s.Printf ("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ", - IsRunning(), - is_reply ? "<--" : "-->", - command_name, - first_packet_byte, - sequence_id, - length, - key); - - if (is_reply) - { - // Dump request reply packets - switch (command) - { - // Commands that return a single 32 bit error - case KDP_CONNECT: - case KDP_WRITEMEM: - case KDP_WRITEMEM64: - case KDP_BREAKPOINT_SET: - case KDP_BREAKPOINT_REMOVE: - case KDP_BREAKPOINT_SET64: - case KDP_BREAKPOINT_REMOVE64: - case KDP_WRITEREGS: - case KDP_LOAD: - case KDP_WRITEIOPORT: - case KDP_WRITEMSR64: - { - const uint32_t error = packet.GetU32 (&offset); - s.Printf(" (error=0x%8.8x)", error); - } - break; - - case KDP_DISCONNECT: - case KDP_REATTACH: - case KDP_HOSTREBOOT: - case KDP_SUSPEND: - case KDP_RESUMECPUS: - case KDP_EXCEPTION: - case KDP_TERMINATION: - // No return value for the reply, just the header to ack - s.PutCString(" ()"); - break; - - case KDP_HOSTINFO: - { - const uint32_t cpu_mask = packet.GetU32 (&offset); - const uint32_t cpu_type = packet.GetU32 (&offset); - const uint32_t cpu_subtype = packet.GetU32 (&offset); - s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype); - } - break; - - case KDP_VERSION: - { - const uint32_t version = packet.GetU32 (&offset); - const uint32_t feature = packet.GetU32 (&offset); - s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature); - } - break; - - case KDP_REGIONS: - { - const uint32_t region_count = packet.GetU32 (&offset); - s.Printf(" (count = %u", region_count); - for (uint32_t i=0; i<region_count; ++i) - { - const addr_t region_addr = packet.GetPointer (&offset); - const uint32_t region_size = packet.GetU32 (&offset); - const uint32_t region_prot = packet.GetU32 (&offset); - s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot)); - } - } - break; - - case KDP_READMEM: - case KDP_READMEM64: - case KDP_READPHYSMEM64: - { - const uint32_t error = packet.GetU32 (&offset); - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (error = 0x%8.8x:\n", error); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatBytesWithASCII, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - m_last_read_memory_addr, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - case KDP_READREGS: - { - const uint32_t error = packet.GetU32 (&offset); - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (error = 0x%8.8x regs:\n", error); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - m_addr_byte_size, // Size of each item in bytes - count / m_addr_byte_size, // Number of items - 16 / m_addr_byte_size, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - case KDP_KERNELVERSION: - { - const char *kernel_version = packet.PeekCStr(8); - s.Printf(" (version = \"%s\")", kernel_version); - } - break; - - case KDP_MAXBYTES: - { - const uint32_t max_bytes = packet.GetU32 (&offset); - s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes); - } - break; - case KDP_IMAGEPATH: - { - const char *path = packet.GetCStr(&offset); - s.Printf(" (path = \"%s\")", path); - } - break; - - case KDP_READIOPORT: - case KDP_READMSR64: - { - const uint32_t error = packet.GetU32 (&offset); - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (error = 0x%8.8x io:\n", error); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - case KDP_DUMPINFO: - { - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (count = %u, bytes = \n", count); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - - } - break; - - default: - s.Printf(" (add support for dumping this packet reply!!!"); - break; - - } - } - else - { - // Dump request packets - switch (command) - { - case KDP_CONNECT: - { - const uint16_t reply_port = ntohs(packet.GetU16 (&offset)); - const uint16_t exc_port = ntohs(packet.GetU16 (&offset)); - s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset)); - } - break; - - case KDP_DISCONNECT: - case KDP_HOSTREBOOT: - case KDP_HOSTINFO: - case KDP_VERSION: - case KDP_REGIONS: - case KDP_KERNELVERSION: - case KDP_MAXBYTES: - case KDP_IMAGEPATH: - case KDP_SUSPEND: - // No args, just the header in the request... - s.PutCString(" ()"); - break; - - case KDP_RESUMECPUS: - { - const uint32_t cpu_mask = packet.GetU32 (&offset); - s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask); - } - break; - - case KDP_READMEM: - { - const uint32_t addr = packet.GetU32 (&offset); - const uint32_t size = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size); - m_last_read_memory_addr = addr; - } - break; - - case KDP_WRITEMEM: - { - const uint32_t addr = packet.GetU32 (&offset); - const uint32_t size = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size); - if (size > 0) - DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); - } - break; - - case KDP_READMEM64: - { - const uint64_t addr = packet.GetU64 (&offset); - const uint32_t size = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size); - m_last_read_memory_addr = addr; - } - break; - - case KDP_READPHYSMEM64: - { - const uint64_t addr = packet.GetU64 (&offset); - const uint32_t size = packet.GetU32 (&offset); - const uint32_t lcpu = packet.GetU16 (&offset); - s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size, lcpu); - m_last_read_memory_addr = addr; - } - break; - - case KDP_WRITEMEM64: - { - const uint64_t addr = packet.GetU64 (&offset); - const uint32_t size = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, size); - if (size > 0) - DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); - } - break; - - case KDP_WRITEPHYSMEM64: - { - const uint64_t addr = packet.GetU64 (&offset); - const uint32_t size = packet.GetU32 (&offset); - const uint32_t lcpu = packet.GetU16 (&offset); - s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", addr, size, lcpu); - if (size > 0) - DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); - } - break; - - case KDP_READREGS: - { - const uint32_t cpu = packet.GetU32 (&offset); - const uint32_t flavor = packet.GetU32 (&offset); - s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor); - } - break; - - case KDP_WRITEREGS: - { - const uint32_t cpu = packet.GetU32 (&offset); - const uint32_t flavor = packet.GetU32 (&offset); - const uint32_t nbytes = packet.GetByteSize() - offset; - s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor); - if (nbytes > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - m_addr_byte_size, // Size of each item in bytes - nbytes / m_addr_byte_size, // Number of items - 16 / m_addr_byte_size, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - - case KDP_BREAKPOINT_SET: - case KDP_BREAKPOINT_REMOVE: - { - const uint32_t addr = packet.GetU32 (&offset); - s.Printf(" (addr = 0x%8.8x)", addr); - } - break; - - case KDP_BREAKPOINT_SET64: - case KDP_BREAKPOINT_REMOVE64: - { - const uint64_t addr = packet.GetU64 (&offset); - s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr); - } - break; - - - case KDP_LOAD: - { - const char *path = packet.GetCStr(&offset); - s.Printf(" (path = \"%s\")", path); - } - break; - - case KDP_EXCEPTION: - { - const uint32_t count = packet.GetU32 (&offset); - - for (uint32_t i=0; i<count; ++i) - { - const uint32_t cpu = packet.GetU32 (&offset); - const uint32_t exc = packet.GetU32 (&offset); - const uint32_t code = packet.GetU32 (&offset); - const uint32_t subcode = packet.GetU32 (&offset); - const char *exc_cstr = NULL; - switch (exc) - { - case 1: exc_cstr = "EXC_BAD_ACCESS"; break; - case 2: exc_cstr = "EXC_BAD_INSTRUCTION"; break; - case 3: exc_cstr = "EXC_ARITHMETIC"; break; - case 4: exc_cstr = "EXC_EMULATION"; break; - case 5: exc_cstr = "EXC_SOFTWARE"; break; - case 6: exc_cstr = "EXC_BREAKPOINT"; break; - case 7: exc_cstr = "EXC_SYSCALL"; break; - case 8: exc_cstr = "EXC_MACH_SYSCALL"; break; - case 9: exc_cstr = "EXC_RPC_ALERT"; break; - case 10: exc_cstr = "EXC_CRASH"; break; - default: - break; - } - - s.Printf ("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)} ", - cpu, exc_cstr, exc, code, code, subcode, subcode); - } - } - break; - - case KDP_TERMINATION: - { - const uint32_t term_code = packet.GetU32 (&offset); - const uint32_t exit_code = packet.GetU32 (&offset); - s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code); - } - break; - - case KDP_REATTACH: - { - const uint16_t reply_port = ntohs(packet.GetU16 (&offset)); - s.Printf(" (reply_port = %u)", reply_port); - } - break; - - case KDP_READMSR64: - { - const uint32_t address = packet.GetU32 (&offset); - const uint16_t lcpu = packet.GetU16 (&offset); - s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu); - } - break; - - case KDP_WRITEMSR64: - { - const uint32_t address = packet.GetU32 (&offset); - const uint16_t lcpu = packet.GetU16 (&offset); - const uint32_t nbytes = packet.GetByteSize() - offset; - s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, address, nbytes); - if (nbytes > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - nbytes, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - case KDP_READIOPORT: - { - const uint16_t lcpu = packet.GetU16 (&offset); - const uint16_t address = packet.GetU16 (&offset); - const uint16_t nbytes = packet.GetU16 (&offset); - s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address, nbytes); - } - break; - - case KDP_WRITEIOPORT: - { - const uint16_t lcpu = packet.GetU16 (&offset); - const uint16_t address = packet.GetU16 (&offset); - const uint16_t nbytes = packet.GetU16 (&offset); - s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, address, nbytes); - if (nbytes > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - nbytes, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - } - break; - - case KDP_DUMPINFO: - { - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (count = %u, bytes = \n", count); - if (count > 0) - packet.Dump (&s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - - } - break; - - } - } - } - else - { - error_desc = "error: invalid packet command: "; - } - } - - if (error_desc) - { - s.PutCString (error_desc); - - packet.Dump (&s, // Stream to dump to - 0, // Offset into "packet" - eFormatBytes, // Dump as hex bytes - 1, // Size of each item is 1 for single bytes - packet.GetByteSize(), // Number of bytes - UINT32_MAX, // Num bytes per line - LLDB_INVALID_ADDRESS, // Base address - 0, 0); // Bitfield info set to not do anything bitfield related - } +void CommunicationKDP::DumpPacket(Stream &s, const void *data, + uint32_t data_len) { + DataExtractor extractor(data, data_len, m_byte_order, m_addr_byte_size); + DumpPacket(s, extractor); } -uint32_t -CommunicationKDP::SendRequestReadRegisters (uint32_t cpu, - uint32_t flavor, - void *dst, - uint32_t dst_len, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_READREGS; - // Size is header + 4 byte cpu and 4 byte flavor - const uint32_t command_length = 8 + 4 + 4; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutHex32 (cpu); - request_packet.PutHex32 (flavor); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - uint32_t src_len = reply_packet.GetByteSize() - 12; - - if (src_len > 0) - { - const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len); - const void *src = reply_packet.GetData(&offset, bytes_to_copy); - if (src) - { - ::memcpy (dst, src, bytes_to_copy); - error.Clear(); - // Return the number of bytes we could have returned regardless if - // we copied them or not, just so we know when things don't match up - return src_len; +void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { + const char *error_desc = NULL; + if (packet.GetByteSize() < 8) { + error_desc = "error: invalid packet (too short): "; + } else { + lldb::offset_t offset = 0; + const uint8_t first_packet_byte = packet.GetU8(&offset); + const uint8_t sequence_id = packet.GetU8(&offset); + const uint16_t length = packet.GetU16(&offset); + const uint32_t key = packet.GetU32(&offset); + const CommandType command = ExtractCommand(first_packet_byte); + const char *command_name = GetCommandAsCString(command); + if (command_name) { + const bool is_reply = ExtractIsReply(first_packet_byte); + s.Printf("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ", + IsRunning(), is_reply ? "<--" : "-->", command_name, + first_packet_byte, sequence_id, length, key); + + if (is_reply) { + // Dump request reply packets + switch (command) { + // Commands that return a single 32 bit error + case KDP_CONNECT: + case KDP_WRITEMEM: + case KDP_WRITEMEM64: + case KDP_BREAKPOINT_SET: + case KDP_BREAKPOINT_REMOVE: + case KDP_BREAKPOINT_SET64: + case KDP_BREAKPOINT_REMOVE64: + case KDP_WRITEREGS: + case KDP_LOAD: + case KDP_WRITEIOPORT: + case KDP_WRITEMSR64: { + const uint32_t error = packet.GetU32(&offset); + s.Printf(" (error=0x%8.8x)", error); + } break; + + case KDP_DISCONNECT: + case KDP_REATTACH: + case KDP_HOSTREBOOT: + case KDP_SUSPEND: + case KDP_RESUMECPUS: + case KDP_EXCEPTION: + case KDP_TERMINATION: + // No return value for the reply, just the header to ack + s.PutCString(" ()"); + break; + + case KDP_HOSTINFO: { + const uint32_t cpu_mask = packet.GetU32(&offset); + const uint32_t cpu_type = packet.GetU32(&offset); + const uint32_t cpu_subtype = packet.GetU32(&offset); + s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", + cpu_mask, cpu_type, cpu_subtype); + } break; + + case KDP_VERSION: { + const uint32_t version = packet.GetU32(&offset); + const uint32_t feature = packet.GetU32(&offset); + s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature); + } break; + + case KDP_REGIONS: { + const uint32_t region_count = packet.GetU32(&offset); + s.Printf(" (count = %u", region_count); + for (uint32_t i = 0; i < region_count; ++i) { + const addr_t region_addr = packet.GetPointer(&offset); + const uint32_t region_size = packet.GetU32(&offset); + const uint32_t region_prot = packet.GetU32(&offset); + s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 + " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", + region_addr, region_addr, region_addr + region_size, + region_size, GetPermissionsAsCString(region_prot)); + } + } break; + + case KDP_READMEM: + case KDP_READMEM64: + case KDP_READPHYSMEM64: { + const uint32_t error = packet.GetU32(&offset); + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (error = 0x%8.8x:\n", error); + if (count > 0) + packet.Dump(&s, // Stream to dump to + offset, // Offset within "packet" + eFormatBytesWithASCII, // Format to use + 1, // Size of each item in bytes + count, // Number of items + 16, // Number per line + m_last_read_memory_addr, // Don't show addresses before + // each line + 0, 0); // No bitfields + } break; + + case KDP_READREGS: { + const uint32_t error = packet.GetU32(&offset); + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (error = 0x%8.8x regs:\n", error); + if (count > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + m_addr_byte_size, // Size of each item in bytes + count / m_addr_byte_size, // Number of items + 16 / m_addr_byte_size, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + + case KDP_KERNELVERSION: { + const char *kernel_version = packet.PeekCStr(8); + s.Printf(" (version = \"%s\")", kernel_version); + } break; + + case KDP_MAXBYTES: { + const uint32_t max_bytes = packet.GetU32(&offset); + s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes); + } break; + case KDP_IMAGEPATH: { + const char *path = packet.GetCStr(&offset); + s.Printf(" (path = \"%s\")", path); + } break; + + case KDP_READIOPORT: + case KDP_READMSR64: { + const uint32_t error = packet.GetU32(&offset); + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (error = 0x%8.8x io:\n", error); + if (count > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + count, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + case KDP_DUMPINFO: { + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (count = %u, bytes = \n", count); + if (count > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + count, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + + } break; + + default: + s.Printf(" (add support for dumping this packet reply!!!"); + break; + } + } else { + // Dump request packets + switch (command) { + case KDP_CONNECT: { + const uint16_t reply_port = ntohs(packet.GetU16(&offset)); + const uint16_t exc_port = ntohs(packet.GetU16(&offset)); + s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", + reply_port, exc_port, packet.GetCStr(&offset)); + } break; + + case KDP_DISCONNECT: + case KDP_HOSTREBOOT: + case KDP_HOSTINFO: + case KDP_VERSION: + case KDP_REGIONS: + case KDP_KERNELVERSION: + case KDP_MAXBYTES: + case KDP_IMAGEPATH: + case KDP_SUSPEND: + // No args, just the header in the request... + s.PutCString(" ()"); + break; + + case KDP_RESUMECPUS: { + const uint32_t cpu_mask = packet.GetU32(&offset); + s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask); + } break; + + case KDP_READMEM: { + const uint32_t addr = packet.GetU32(&offset); + const uint32_t size = packet.GetU32(&offset); + s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size); + m_last_read_memory_addr = addr; + } break; + + case KDP_WRITEMEM: { + const uint32_t addr = packet.GetU32(&offset); + const uint32_t size = packet.GetU32(&offset); + s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size); + if (size > 0) + DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, + 32, addr); + } break; + + case KDP_READMEM64: { + const uint64_t addr = packet.GetU64(&offset); + const uint32_t size = packet.GetU32(&offset); + s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size); + m_last_read_memory_addr = addr; + } break; + + case KDP_READPHYSMEM64: { + const uint64_t addr = packet.GetU64(&offset); + const uint32_t size = packet.GetU32(&offset); + const uint32_t lcpu = packet.GetU16(&offset); + s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size, + lcpu); + m_last_read_memory_addr = addr; + } break; + + case KDP_WRITEMEM64: { + const uint64_t addr = packet.GetU64(&offset); + const uint32_t size = packet.GetU32(&offset); + s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, + size); + if (size > 0) + DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, + 32, addr); + } break; + + case KDP_WRITEPHYSMEM64: { + const uint64_t addr = packet.GetU64(&offset); + const uint32_t size = packet.GetU32(&offset); + const uint32_t lcpu = packet.GetU16(&offset); + s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", + addr, size, lcpu); + if (size > 0) + DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, + 32, addr); + } break; + + case KDP_READREGS: { + const uint32_t cpu = packet.GetU32(&offset); + const uint32_t flavor = packet.GetU32(&offset); + s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor); + } break; + + case KDP_WRITEREGS: { + const uint32_t cpu = packet.GetU32(&offset); + const uint32_t flavor = packet.GetU32(&offset); + const uint32_t nbytes = packet.GetByteSize() - offset; + s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor); + if (nbytes > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + m_addr_byte_size, // Size of each item in bytes + nbytes / m_addr_byte_size, // Number of items + 16 / m_addr_byte_size, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + + case KDP_BREAKPOINT_SET: + case KDP_BREAKPOINT_REMOVE: { + const uint32_t addr = packet.GetU32(&offset); + s.Printf(" (addr = 0x%8.8x)", addr); + } break; + + case KDP_BREAKPOINT_SET64: + case KDP_BREAKPOINT_REMOVE64: { + const uint64_t addr = packet.GetU64(&offset); + s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr); + } break; + + case KDP_LOAD: { + const char *path = packet.GetCStr(&offset); + s.Printf(" (path = \"%s\")", path); + } break; + + case KDP_EXCEPTION: { + const uint32_t count = packet.GetU32(&offset); + + for (uint32_t i = 0; i < count; ++i) { + const uint32_t cpu = packet.GetU32(&offset); + const uint32_t exc = packet.GetU32(&offset); + const uint32_t code = packet.GetU32(&offset); + const uint32_t subcode = packet.GetU32(&offset); + const char *exc_cstr = NULL; + switch (exc) { + case 1: + exc_cstr = "EXC_BAD_ACCESS"; + break; + case 2: + exc_cstr = "EXC_BAD_INSTRUCTION"; + break; + case 3: + exc_cstr = "EXC_ARITHMETIC"; + break; + case 4: + exc_cstr = "EXC_EMULATION"; + break; + case 5: + exc_cstr = "EXC_SOFTWARE"; + break; + case 6: + exc_cstr = "EXC_BREAKPOINT"; + break; + case 7: + exc_cstr = "EXC_SYSCALL"; + break; + case 8: + exc_cstr = "EXC_MACH_SYSCALL"; + break; + case 9: + exc_cstr = "EXC_RPC_ALERT"; + break; + case 10: + exc_cstr = "EXC_CRASH"; + break; + default: + break; } + + s.Printf("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), " + "subcode = %u (0x%8.8x)} ", + cpu, exc_cstr, exc, code, code, subcode, subcode); + } + } break; + + case KDP_TERMINATION: { + const uint32_t term_code = packet.GetU32(&offset); + const uint32_t exit_code = packet.GetU32(&offset); + s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", + term_code, term_code, exit_code, exit_code); + } break; + + case KDP_REATTACH: { + const uint16_t reply_port = ntohs(packet.GetU16(&offset)); + s.Printf(" (reply_port = %u)", reply_port); + } break; + + case KDP_READMSR64: { + const uint32_t address = packet.GetU32(&offset); + const uint16_t lcpu = packet.GetU16(&offset); + s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu); + } break; + + case KDP_WRITEMSR64: { + const uint32_t address = packet.GetU32(&offset); + const uint16_t lcpu = packet.GetU16(&offset); + const uint32_t nbytes = packet.GetByteSize() - offset; + s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, + address, nbytes); + if (nbytes > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + nbytes, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + + case KDP_READIOPORT: { + const uint16_t lcpu = packet.GetU16(&offset); + const uint16_t address = packet.GetU16(&offset); + const uint16_t nbytes = packet.GetU16(&offset); + s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address, + nbytes); + } break; + + case KDP_WRITEIOPORT: { + const uint16_t lcpu = packet.GetU16(&offset); + const uint16_t address = packet.GetU16(&offset); + const uint16_t nbytes = packet.GetU16(&offset); + s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, + address, nbytes); + if (nbytes > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + nbytes, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + } break; + + case KDP_DUMPINFO: { + const uint32_t count = packet.GetByteSize() - offset; + s.Printf(" (count = %u, bytes = \n", count); + if (count > 0) + packet.Dump( + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + count, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses before each line + 0, 0); // No bitfields + + } break; } - if (kdp_error) - error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error); - else - error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor); + } + } else { + error_desc = "error: invalid packet command: "; } - else - { - error.SetErrorString ("failed to send packet"); - } - return 0; + } + + if (error_desc) { + s.PutCString(error_desc); + + packet.Dump(&s, // Stream to dump to + 0, // Offset into "packet" + eFormatBytes, // Dump as hex bytes + 1, // Size of each item is 1 for single bytes + packet.GetByteSize(), // Number of bytes + UINT32_MAX, // Num bytes per line + LLDB_INVALID_ADDRESS, // Base address + 0, 0); // Bitfield info set to not do anything bitfield related + } } -uint32_t -CommunicationKDP::SendRequestWriteRegisters (uint32_t cpu, - uint32_t flavor, - const void *src, - uint32_t src_len, - Error &error) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_WRITEREGS; - // Size is header + 4 byte cpu and 4 byte flavor - const uint32_t command_length = 8 + 4 + 4 + src_len; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutHex32 (cpu); - request_packet.PutHex32 (flavor); - request_packet.Write(src, src_len); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - if (kdp_error == 0) - return src_len; - error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error); +uint32_t CommunicationKDP::SendRequestReadRegisters(uint32_t cpu, + uint32_t flavor, void *dst, + uint32_t dst_len, + Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_READREGS; + // Size is header + 4 byte cpu and 4 byte flavor + const uint32_t command_length = 8 + 4 + 4; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutHex32(cpu); + request_packet.PutHex32(flavor); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + uint32_t src_len = reply_packet.GetByteSize() - 12; + + if (src_len > 0) { + const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len); + const void *src = reply_packet.GetData(&offset, bytes_to_copy); + if (src) { + ::memcpy(dst, src, bytes_to_copy); + error.Clear(); + // Return the number of bytes we could have returned regardless if + // we copied them or not, just so we know when things don't match up + return src_len; + } } + if (kdp_error) + error.SetErrorStringWithFormat( + "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, + flavor, kdp_error); else - { - error.SetErrorString ("failed to send packet"); - } - return 0; + error.SetErrorStringWithFormat( + "failed to read kdp registers for cpu %u flavor %u", cpu, flavor); + } else { + error.SetErrorString("failed to send packet"); + } + return 0; } - -bool -CommunicationKDP::SendRequestResume () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_RESUMECPUS; - const uint32_t command_length = 12; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutHex32(GetCPUMask()); - - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - return true; - return false; +uint32_t CommunicationKDP::SendRequestWriteRegisters(uint32_t cpu, + uint32_t flavor, + const void *src, + uint32_t src_len, + Error &error) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_WRITEREGS; + // Size is header + 4 byte cpu and 4 byte flavor + const uint32_t command_length = 8 + 4 + 4 + src_len; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutHex32(cpu); + request_packet.PutHex32(flavor); + request_packet.Write(src, src_len); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + if (kdp_error == 0) + return src_len; + error.SetErrorStringWithFormat( + "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, + flavor, kdp_error); + } else { + error.SetErrorString("failed to send packet"); + } + return 0; } -bool -CommunicationKDP::SendRequestBreakpoint (bool set, addr_t addr) -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - bool use_64 = (GetVersion() >= 11); - uint32_t command_addr_byte_size = use_64 ? 8 : 4; - const CommandType command = set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET ): - (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE); +bool CommunicationKDP::SendRequestResume() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_RESUMECPUS; + const uint32_t command_length = 12; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutHex32(GetCPUMask()); - const uint32_t command_length = 8 + command_addr_byte_size; - MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutMaxHex64 (addr, command_addr_byte_size); - - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32 (&offset); - if (kdp_error == 0) - return true; - } - return false; + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) + return true; + return false; } -bool -CommunicationKDP::SendRequestSuspend () -{ - PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); - const CommandType command = KDP_SUSPEND; - const uint32_t command_length = 8; - MakeRequestPacketHeader (command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply (command, request_packet, reply_packet)) - return true; - return false; +bool CommunicationKDP::SendRequestBreakpoint(bool set, addr_t addr) { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + bool use_64 = (GetVersion() >= 11); + uint32_t command_addr_byte_size = use_64 ? 8 : 4; + const CommandType command = + set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET) + : (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE); + + const uint32_t command_length = 8 + command_addr_byte_size; + MakeRequestPacketHeader(command, request_packet, command_length); + request_packet.PutMaxHex64(addr, command_addr_byte_size); + + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) { + lldb::offset_t offset = 8; + uint32_t kdp_error = reply_packet.GetU32(&offset); + if (kdp_error == 0) + return true; + } + return false; } +bool CommunicationKDP::SendRequestSuspend() { + PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, + m_byte_order); + const CommandType command = KDP_SUSPEND; + const uint32_t command_length = 8; + MakeRequestPacketHeader(command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply(command, request_packet, reply_packet)) + return true; + return false; +} |