//===-- 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 // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Listener.h" #include "lldb/Core/StreamBuffer.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/TimeValue.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(lldb_private::Mutex::Locker& locker); 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. //------------------------------------------------------------------ uint32_t SetPacketTimeout (uint32_t packet_timeout) { const uint32_t old_packet_timeout = m_packet_timeout; m_packet_timeout = packet_timeout; return old_packet_timeout; } uint32_t GetPacketTimeoutInMicroSeconds () const { return m_packet_timeout * lldb_private::TimeValue::MicroSecPerSec; } //------------------------------------------------------------------ // Start a debugserver instance on the current host using the // supplied connection URL. //------------------------------------------------------------------ lldb_private::Error StartDebugserverProcess (const char *connect_url, const char *unix_socket_name, lldb_private::ProcessLaunchInfo &launch_info); //------------------------------------------------------------------ // 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::Error &error); uint32_t SendRequestWriteMemory (lldb::addr_t addr, const void *src, uint32_t src_len, lldb_private::Error &error); bool SendRawRequest (uint8_t command_byte, const void *src, uint32_t src_len, lldb_private::DataExtractor &reply, lldb_private::Error &error); uint32_t SendRequestReadRegisters (uint32_t cpu, uint32_t flavor, void *dst, uint32_t dst_size, lldb_private::Error &error); uint32_t SendRequestWriteRegisters (uint32_t cpu, uint32_t flavor, const void *src, uint32_t src_size, lldb_private::Error &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 lldb_private::TimeValue *timeout_ptr); 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; uint32_t m_packet_timeout; lldb_private::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_