//===-- CommunicationKDP.h --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_CommunicationKDP_h_ #define liblldb_CommunicationKDP_h_ // C Includes // C++ Includes #include #include #include // Other libraries and framework includes // Project includes #include "lldb/Core/Communication.h" #include "lldb/Core/Listener.h" #include "lldb/Core/StreamBuffer.h" #include "lldb/Host/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<1024> PacketStreamType; typedef enum { 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 } CommandType; enum { KDP_FEATURE_BP = (1u << 0) }; typedef enum { KDP_PROTERR_SUCCESS = 0, KDP_PROTERR_ALREADY_CONNECTED, KDP_PROTERR_BAD_NBYTES, KDP_PROTERR_BADFLAVOR } KDPError; typedef enum { ePacketTypeRequest = 0x00u, ePacketTypeReply = 0x80u, ePacketTypeMask = 0x80u, eCommandTypeMask = 0x7fu } PacketType; //------------------------------------------------------------------ // 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 //------------------------------------------------------------------ DISALLOW_COPY_AND_ASSIGN(CommunicationKDP); }; #endif // liblldb_CommunicationKDP_h_