348 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			348 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- 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 <list>
 | |
| #include <string>
 | |
| 
 | |
| // 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;
 | |
|     }
 | |
|     
 | |
|     //------------------------------------------------------------------
 | |
|     // 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<bool> 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_
 |