1//===-- GDBRemoteCommunication.h --------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef liblldb_GDBRemoteCommunication_h_ 11#define liblldb_GDBRemoteCommunication_h_ 12 13// C Includes 14// C++ Includes 15#include <list> 16#include <string> 17 18// Other libraries and framework includes 19// Project includes 20#include "lldb/lldb-public.h" 21#include "lldb/Core/Communication.h" 22#include "lldb/Core/Listener.h" 23#include "lldb/Host/Mutex.h" 24#include "lldb/Host/Predicate.h" 25#include "lldb/Host/TimeValue.h" 26 27#include "Utility/StringExtractorGDBRemote.h" 28 29class ProcessGDBRemote; 30 31class GDBRemoteCommunication : public lldb_private::Communication 32{ 33public: 34 enum 35 { 36 eBroadcastBitRunPacketSent = kLoUserBroadcastBit 37 }; 38 39 enum class PacketResult 40 { 41 Success = 0, // Success 42 ErrorSendFailed, // Error sending the packet 43 ErrorSendAck, // Didn't get an ack back after sending a packet 44 ErrorReplyFailed, // Error getting the reply 45 ErrorReplyTimeout, // Timed out waiting for reply 46 ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that was sent 47 ErrorReplyAck, // Sending reply ack failed 48 ErrorDisconnected, // We were disconnected 49 ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet request 50 }; 51 //------------------------------------------------------------------ 52 // Constructors and Destructors 53 //------------------------------------------------------------------ 54 GDBRemoteCommunication(const char *comm_name, 55 const char *listener_name, 56 bool is_platform); 57 58 virtual 59 ~GDBRemoteCommunication(); 60 61 PacketResult 62 GetAck (); 63 64 size_t 65 SendAck (); 66 67 size_t 68 SendNack (); 69 70 char 71 CalculcateChecksum (const char *payload, 72 size_t payload_length); 73 74 bool 75 GetSequenceMutex (lldb_private::Mutex::Locker& locker, const char *failure_message = NULL); 76 77 bool 78 CheckForPacket (const uint8_t *src, 79 size_t src_len, 80 StringExtractorGDBRemote &packet); 81 bool 82 IsRunning() const 83 { 84 return m_public_is_running.GetValue(); 85 } 86 87 bool 88 GetSendAcks () 89 { 90 return m_send_acks; 91 } 92 93 //------------------------------------------------------------------ 94 // Client and server must implement these pure virtual functions 95 //------------------------------------------------------------------ 96 virtual bool 97 GetThreadSuffixSupported () = 0; 98 99 //------------------------------------------------------------------ 100 // Set the global packet timeout. 101 // 102 // For clients, this is the timeout that gets used when sending 103 // packets and waiting for responses. For servers, this might not 104 // get used, and if it doesn't this should be moved to the 105 // GDBRemoteCommunicationClient. 106 //------------------------------------------------------------------ 107 uint32_t 108 SetPacketTimeout (uint32_t packet_timeout) 109 { 110 const uint32_t old_packet_timeout = m_packet_timeout; 111 m_packet_timeout = packet_timeout; 112 return old_packet_timeout; 113 } 114 115 uint32_t 116 GetPacketTimeoutInMicroSeconds () const 117 { 118 return m_packet_timeout * lldb_private::TimeValue::MicroSecPerSec; 119 } 120 //------------------------------------------------------------------ 121 // Start a debugserver instance on the current host using the 122 // supplied connection URL. 123 //------------------------------------------------------------------ 124 lldb_private::Error 125 StartDebugserverProcess (const char *hostname, 126 uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit 127 lldb_private::ProcessLaunchInfo &launch_info, 128 uint16_t &out_port); 129 130 void 131 DumpHistory(lldb_private::Stream &strm); 132 133protected: 134 135 class History 136 { 137 public: 138 enum PacketType 139 { 140 ePacketTypeInvalid = 0, 141 ePacketTypeSend, 142 ePacketTypeRecv 143 }; 144 145 struct Entry 146 { 147 Entry() : 148 packet(), 149 type (ePacketTypeInvalid), 150 bytes_transmitted (0), 151 packet_idx (0), 152 tid (LLDB_INVALID_THREAD_ID) 153 { 154 } 155 156 void 157 Clear () 158 { 159 packet.clear(); 160 type = ePacketTypeInvalid; 161 bytes_transmitted = 0; 162 packet_idx = 0; 163 tid = LLDB_INVALID_THREAD_ID; 164 } 165 std::string packet; 166 PacketType type; 167 uint32_t bytes_transmitted; 168 uint32_t packet_idx; 169 lldb::tid_t tid; 170 }; 171 172 History (uint32_t size); 173 174 ~History (); 175 176 // For single char packets for ack, nack and /x03 177 void 178 AddPacket (char packet_char, 179 PacketType type, 180 uint32_t bytes_transmitted); 181 void 182 AddPacket (const std::string &src, 183 uint32_t src_len, 184 PacketType type, 185 uint32_t bytes_transmitted); 186 187 void 188 Dump (lldb_private::Stream &strm) const; 189 190 void 191 Dump (lldb_private::Log *log) const; 192 193 bool 194 DidDumpToLog () const 195 { 196 return m_dumped_to_log; 197 } 198 199protected: 200 uint32_t 201 GetFirstSavedPacketIndex () const 202 { 203 if (m_total_packet_count < m_packets.size()) 204 return 0; 205 else 206 return m_curr_idx + 1; 207 } 208 209 uint32_t 210 GetNumPacketsInHistory () const 211 { 212 if (m_total_packet_count < m_packets.size()) 213 return m_total_packet_count; 214 else 215 return (uint32_t)m_packets.size(); 216 } 217 218 uint32_t 219 GetNextIndex() 220 { 221 ++m_total_packet_count; 222 const uint32_t idx = m_curr_idx; 223 m_curr_idx = NormalizeIndex(idx + 1); 224 return idx; 225 } 226 227 uint32_t 228 NormalizeIndex (uint32_t i) const 229 { 230 return i % m_packets.size(); 231 } 232 233 234 std::vector<Entry> m_packets; 235 uint32_t m_curr_idx; 236 uint32_t m_total_packet_count; 237 mutable bool m_dumped_to_log; 238 }; 239 240 PacketResult 241 SendPacket (const char *payload, 242 size_t payload_length); 243 244 PacketResult 245 SendPacketNoLock (const char *payload, 246 size_t payload_length); 247 248 PacketResult 249 WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &response, 250 uint32_t timeout_usec); 251 252 bool 253 WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr); 254 255 //------------------------------------------------------------------ 256 // Classes that inherit from GDBRemoteCommunication can see and modify these 257 //------------------------------------------------------------------ 258 uint32_t m_packet_timeout; 259#ifdef ENABLE_MUTEX_ERROR_CHECKING 260 lldb_private::TrackingMutex m_sequence_mutex; 261#else 262 lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time 263#endif 264 lldb_private::Predicate<bool> m_public_is_running; 265 lldb_private::Predicate<bool> m_private_is_running; 266 History m_history; 267 bool m_send_acks; 268 bool m_is_platform; // Set to true if this class represents a platform, 269 // false if this class represents a debug session for 270 // a single process 271 272 273 lldb_private::Error 274 StartListenThread (const char *hostname = "localhost", 275 uint16_t port = 0); 276 277 bool 278 JoinListenThread (); 279 280 static lldb::thread_result_t 281 ListenThread (lldb::thread_arg_t arg); 282 283private: 284 285 lldb::thread_t m_listen_thread; 286 std::string m_listen_url; 287 288 289 //------------------------------------------------------------------ 290 // For GDBRemoteCommunication only 291 //------------------------------------------------------------------ 292 DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication); 293}; 294 295#endif // liblldb_GDBRemoteCommunication_h_ 296