//===-- CommunicationKDP.h --------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLDB_SOURCE_PLUGINS_PROCESS_MACOSX_KERNEL_COMMUNICATIONKDP_H #define LLDB_SOURCE_PLUGINS_PROCESS_MACOSX_KERNEL_COMMUNICATIONKDP_H #include #include #include #include "lldb/Core/Communication.h" #include "lldb/Core/StreamBuffer.h" #include "lldb/Utility/Listener.h" #include "lldb/Utility/Predicate.h" #include "lldb/lldb-private.h" class CommunicationKDP : public lldb_private::Communication { public: enum { eBroadcastBitRunPacketSent = kLoUserBroadcastBit }; const static uint32_t kMaxPacketSize = 1200; const static uint32_t kMaxDataSize = 1024; typedef lldb_private::StreamBuffer<4096> PacketStreamType; enum CommandType { KDP_CONNECT = 0u, KDP_DISCONNECT, KDP_HOSTINFO, KDP_VERSION, KDP_MAXBYTES, KDP_READMEM, KDP_WRITEMEM, KDP_READREGS, KDP_WRITEREGS, KDP_LOAD, KDP_IMAGEPATH, KDP_SUSPEND, KDP_RESUMECPUS, KDP_EXCEPTION, KDP_TERMINATION, KDP_BREAKPOINT_SET, KDP_BREAKPOINT_REMOVE, KDP_REGIONS, KDP_REATTACH, KDP_HOSTREBOOT, KDP_READMEM64, KDP_WRITEMEM64, KDP_BREAKPOINT_SET64, KDP_BREAKPOINT_REMOVE64, KDP_KERNELVERSION, KDP_READPHYSMEM64, KDP_WRITEPHYSMEM64, KDP_READIOPORT, KDP_WRITEIOPORT, KDP_READMSR64, KDP_WRITEMSR64, KDP_DUMPINFO }; enum { KDP_FEATURE_BP = (1u << 0) }; enum KDPError { KDP_PROTERR_SUCCESS = 0, KDP_PROTERR_ALREADY_CONNECTED, KDP_PROTERR_BAD_NBYTES, KDP_PROTERR_BADFLAVOR }; enum PacketType { ePacketTypeRequest = 0x00u, ePacketTypeReply = 0x80u, ePacketTypeMask = 0x80u, eCommandTypeMask = 0x7fu }; // Constructors and Destructors CommunicationKDP(const char *comm_name); virtual ~CommunicationKDP(); bool SendRequestPacket(const PacketStreamType &request_packet); // Wait for a packet within 'nsec' seconds size_t WaitForPacketWithTimeoutMicroSeconds(lldb_private::DataExtractor &response, uint32_t usec); bool GetSequenceMutex(std::unique_lock &lock); bool CheckForPacket(const uint8_t *src, size_t src_len, lldb_private::DataExtractor &packet); bool IsRunning() const { return m_is_running.GetValue(); } // Set the global packet timeout. // // For clients, this is the timeout that gets used when sending // packets and waiting for responses. For servers, this might not // get used, and if it doesn't this should be moved to the // CommunicationKDPClient. std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) { const auto old_packet_timeout = m_packet_timeout; m_packet_timeout = packet_timeout; return old_packet_timeout; } std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; } // Public Request Packets bool SendRequestConnect(uint16_t reply_port, uint16_t exc_port, const char *greeting); bool SendRequestReattach(uint16_t reply_port); bool SendRequestDisconnect(); uint32_t SendRequestReadMemory(lldb::addr_t addr, void *dst, uint32_t dst_size, lldb_private::Status &error); uint32_t SendRequestWriteMemory(lldb::addr_t addr, const void *src, uint32_t src_len, lldb_private::Status &error); bool SendRawRequest(uint8_t command_byte, const void *src, uint32_t src_len, lldb_private::DataExtractor &reply, lldb_private::Status &error); uint32_t SendRequestReadRegisters(uint32_t cpu, uint32_t flavor, void *dst, uint32_t dst_size, lldb_private::Status &error); uint32_t SendRequestWriteRegisters(uint32_t cpu, uint32_t flavor, const void *src, uint32_t src_size, lldb_private::Status &error); const char *GetKernelVersion(); // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... // const char * // GetImagePath (); uint32_t GetVersion(); uint32_t GetFeatureFlags(); bool LocalBreakpointsAreSupported() { return (GetFeatureFlags() & KDP_FEATURE_BP) != 0; } uint32_t GetCPUMask(); uint32_t GetCPUType(); uint32_t GetCPUSubtype(); lldb_private::UUID GetUUID(); bool RemoteIsEFI(); bool RemoteIsDarwinKernel(); lldb::addr_t GetLoadAddress(); bool SendRequestResume(); bool SendRequestSuspend(); bool SendRequestBreakpoint(bool set, lldb::addr_t addr); protected: bool SendRequestPacketNoLock(const PacketStreamType &request_packet); size_t WaitForPacketWithTimeoutMicroSecondsNoLock( lldb_private::DataExtractor &response, uint32_t timeout_usec); bool WaitForNotRunningPrivate(const std::chrono::microseconds &timeout); void MakeRequestPacketHeader(CommandType request_type, PacketStreamType &request_packet, uint16_t request_length); // Protected Request Packets (use public accessors which will cache // results. bool SendRequestVersion(); bool SendRequestHostInfo(); bool SendRequestKernelVersion(); // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... // bool // SendRequestImagePath (); void DumpPacket(lldb_private::Stream &s, const void *data, uint32_t data_len); void DumpPacket(lldb_private::Stream &s, const lldb_private::DataExtractor &extractor); bool VersionIsValid() const { return m_kdp_version_version != 0; } bool HostInfoIsValid() const { return m_kdp_hostinfo_cpu_type != 0; } bool ExtractIsReply(uint8_t first_packet_byte) const { // TODO: handle big endian... return (first_packet_byte & ePacketTypeMask) != 0; } CommandType ExtractCommand(uint8_t first_packet_byte) const { // TODO: handle big endian... return (CommandType)(first_packet_byte & eCommandTypeMask); } static const char *GetCommandAsCString(uint8_t command); void ClearKDPSettings(); bool SendRequestAndGetReply(const CommandType command, const PacketStreamType &request_packet, lldb_private::DataExtractor &reply_packet); // Classes that inherit from CommunicationKDP can see and modify these uint32_t m_addr_byte_size; lldb::ByteOrder m_byte_order; std::chrono::seconds m_packet_timeout; std::recursive_mutex m_sequence_mutex; // Restrict access to sending/receiving // packets to a single thread at a time lldb_private::Predicate m_is_running; uint32_t m_session_key; uint8_t m_request_sequence_id; uint8_t m_exception_sequence_id; uint32_t m_kdp_version_version; uint32_t m_kdp_version_feature; uint32_t m_kdp_hostinfo_cpu_mask; uint32_t m_kdp_hostinfo_cpu_type; uint32_t m_kdp_hostinfo_cpu_subtype; std::string m_kernel_version; // std::string m_image_path; // Disable KDP_IMAGEPATH for now, it seems to // hang the KDP connection... lldb::addr_t m_last_read_memory_addr; // Last memory read address for logging private: // For CommunicationKDP only CommunicationKDP(const CommunicationKDP &) = delete; const CommunicationKDP &operator=(const CommunicationKDP &) = delete; }; #endif // LLDB_SOURCE_PLUGINS_PROCESS_MACOSX_KERNEL_COMMUNICATIONKDP_H