249 lines · c
1//===-- CommunicationKDP.h --------------------------------------*- C++ -*-===//2//3// 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_PROCESS_MACOSX_KERNEL_COMMUNICATIONKDP_H10#define LLDB_SOURCE_PLUGINS_PROCESS_MACOSX_KERNEL_COMMUNICATIONKDP_H11 12#include <list>13#include <mutex>14#include <string>15 16#include "lldb/Core/Communication.h"17#include "lldb/Utility/Listener.h"18#include "lldb/Utility/Predicate.h"19#include "lldb/Utility/StreamBuffer.h"20#include "lldb/lldb-private.h"21 22class CommunicationKDP : public lldb_private::Communication {23public:24 const static uint32_t kMaxPacketSize = 1200;25 const static uint32_t kMaxDataSize = 1024;26 typedef lldb_private::StreamBuffer<4096> PacketStreamType;27 enum CommandType {28 KDP_CONNECT = 0u,29 KDP_DISCONNECT,30 KDP_HOSTINFO,31 KDP_VERSION,32 KDP_MAXBYTES,33 KDP_READMEM,34 KDP_WRITEMEM,35 KDP_READREGS,36 KDP_WRITEREGS,37 KDP_LOAD,38 KDP_IMAGEPATH,39 KDP_SUSPEND,40 KDP_RESUMECPUS,41 KDP_EXCEPTION,42 KDP_TERMINATION,43 KDP_BREAKPOINT_SET,44 KDP_BREAKPOINT_REMOVE,45 KDP_REGIONS,46 KDP_REATTACH,47 KDP_HOSTREBOOT,48 KDP_READMEM64,49 KDP_WRITEMEM64,50 KDP_BREAKPOINT_SET64,51 KDP_BREAKPOINT_REMOVE64,52 KDP_KERNELVERSION,53 KDP_READPHYSMEM64,54 KDP_WRITEPHYSMEM64,55 KDP_READIOPORT,56 KDP_WRITEIOPORT,57 KDP_READMSR64,58 KDP_WRITEMSR64,59 KDP_DUMPINFO60 };61 62 enum { KDP_FEATURE_BP = (1u << 0) };63 64 enum KDPError {65 KDP_PROTERR_SUCCESS = 0,66 KDP_PROTERR_ALREADY_CONNECTED,67 KDP_PROTERR_BAD_NBYTES,68 KDP_PROTERR_BADFLAVOR69 };70 71 enum PacketType {72 ePacketTypeRequest = 0x00u,73 ePacketTypeReply = 0x80u,74 ePacketTypeMask = 0x80u,75 eCommandTypeMask = 0x7fu76 };77 // Constructors and Destructors78 CommunicationKDP(const char *comm_name);79 80 ~CommunicationKDP() override;81 82 bool SendRequestPacket(const PacketStreamType &request_packet);83 84 // Wait for a packet within 'nsec' seconds85 size_t86 WaitForPacketWithTimeoutMicroSeconds(lldb_private::DataExtractor &response,87 uint32_t usec);88 89 bool GetSequenceMutex(std::unique_lock<std::recursive_mutex> &lock);90 91 bool CheckForPacket(const uint8_t *src, size_t src_len,92 lldb_private::DataExtractor &packet);93 bool IsRunning() const { return m_is_running.GetValue(); }94 95 // Set the global packet timeout.96 //97 // For clients, this is the timeout that gets used when sending98 // packets and waiting for responses. For servers, this might not99 // get used, and if it doesn't this should be moved to the100 // CommunicationKDPClient.101 std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) {102 const auto old_packet_timeout = m_packet_timeout;103 m_packet_timeout = packet_timeout;104 return old_packet_timeout;105 }106 107 std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; }108 109 // Public Request Packets110 bool SendRequestConnect(uint16_t reply_port, uint16_t exc_port,111 const char *greeting);112 113 bool SendRequestReattach(uint16_t reply_port);114 115 bool SendRequestDisconnect();116 117 uint32_t SendRequestReadMemory(lldb::addr_t addr, void *dst,118 uint32_t dst_size,119 lldb_private::Status &error);120 121 uint32_t SendRequestWriteMemory(lldb::addr_t addr, const void *src,122 uint32_t src_len,123 lldb_private::Status &error);124 125 bool SendRawRequest(uint8_t command_byte, const void *src, uint32_t src_len,126 lldb_private::DataExtractor &reply,127 lldb_private::Status &error);128 129 uint32_t SendRequestReadRegisters(uint32_t cpu, uint32_t flavor, void *dst,130 uint32_t dst_size,131 lldb_private::Status &error);132 133 uint32_t SendRequestWriteRegisters(uint32_t cpu, uint32_t flavor,134 const void *src, uint32_t src_size,135 lldb_private::Status &error);136 137 const char *GetKernelVersion();138 139 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...140 // const char *141 // GetImagePath ();142 143 uint32_t GetVersion();144 145 uint32_t GetFeatureFlags();146 147 bool LocalBreakpointsAreSupported() {148 return (GetFeatureFlags() & KDP_FEATURE_BP) != 0;149 }150 151 uint32_t GetCPUMask();152 153 uint32_t GetCPUType();154 155 uint32_t GetCPUSubtype();156 157 lldb_private::UUID GetUUID();158 159 bool RemoteIsEFI();160 161 bool RemoteIsDarwinKernel();162 163 lldb::addr_t GetLoadAddress();164 165 bool SendRequestResume();166 167 bool SendRequestSuspend();168 169 bool SendRequestBreakpoint(bool set, lldb::addr_t addr);170 171protected:172 bool SendRequestPacketNoLock(const PacketStreamType &request_packet);173 174 size_t WaitForPacketWithTimeoutMicroSecondsNoLock(175 lldb_private::DataExtractor &response, uint32_t timeout_usec);176 177 bool WaitForNotRunningPrivate(const std::chrono::microseconds &timeout);178 179 void MakeRequestPacketHeader(CommandType request_type,180 PacketStreamType &request_packet,181 uint16_t request_length);182 183 // Protected Request Packets (use public accessors which will cache184 // results.185 bool SendRequestVersion();186 187 bool SendRequestHostInfo();188 189 bool SendRequestKernelVersion();190 191 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...192 // bool193 // SendRequestImagePath ();194 195 void DumpPacket(lldb_private::Stream &s, const void *data, uint32_t data_len);196 197 void DumpPacket(lldb_private::Stream &s,198 const lldb_private::DataExtractor &extractor);199 200 bool VersionIsValid() const { return m_kdp_version_version != 0; }201 202 bool HostInfoIsValid() const { return m_kdp_hostinfo_cpu_type != 0; }203 204 bool ExtractIsReply(uint8_t first_packet_byte) const {205 // TODO: handle big endian...206 return (first_packet_byte & ePacketTypeMask) != 0;207 }208 209 CommandType ExtractCommand(uint8_t first_packet_byte) const {210 // TODO: handle big endian...211 return (CommandType)(first_packet_byte & eCommandTypeMask);212 }213 214 static const char *GetCommandAsCString(uint8_t command);215 216 void ClearKDPSettings();217 218 bool SendRequestAndGetReply(const CommandType command,219 const PacketStreamType &request_packet,220 lldb_private::DataExtractor &reply_packet);221 // Classes that inherit from CommunicationKDP can see and modify these222 uint32_t m_addr_byte_size;223 lldb::ByteOrder m_byte_order;224 std::string m_bytes;225 std::recursive_mutex m_bytes_mutex;226 std::chrono::seconds m_packet_timeout;227 std::recursive_mutex m_sequence_mutex; // Restrict access to sending/receiving228 // packets to a single thread at a time229 lldb_private::Predicate<bool> m_is_running;230 uint32_t m_session_key;231 uint8_t m_request_sequence_id;232 uint8_t m_exception_sequence_id;233 uint32_t m_kdp_version_version;234 uint32_t m_kdp_version_feature;235 uint32_t m_kdp_hostinfo_cpu_mask;236 uint32_t m_kdp_hostinfo_cpu_type;237 uint32_t m_kdp_hostinfo_cpu_subtype;238 std::string m_kernel_version;239 // std::string m_image_path; // Disable KDP_IMAGEPATH for now, it seems to240 // hang the KDP connection...241 lldb::addr_t m_last_read_memory_addr; // Last memory read address for logging242private:243 // For CommunicationKDP only244 CommunicationKDP(const CommunicationKDP &) = delete;245 const CommunicationKDP &operator=(const CommunicationKDP &) = delete;246};247 248#endif // LLDB_SOURCE_PLUGINS_PROCESS_MACOSX_KERNEL_COMMUNICATIONKDP_H249