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 
29 class ProcessGDBRemote;
30 
31 class GDBRemoteCommunication : public lldb_private::Communication
32 {
33 public:
34     enum
35     {
36         eBroadcastBitRunPacketSent = kLoUserBroadcastBit
37     };
38     //------------------------------------------------------------------
39     // Constructors and Destructors
40     //------------------------------------------------------------------
41     GDBRemoteCommunication(const char *comm_name,
42                            const char *listener_name,
43                            bool is_platform);
44 
45     virtual
46     ~GDBRemoteCommunication();
47 
48     char
49     GetAck ();
50 
51     size_t
52     SendAck ();
53 
54     size_t
55     SendNack ();
56 
57     char
58     CalculcateChecksum (const char *payload,
59                         size_t payload_length);
60 
61     bool
62     GetSequenceMutex (lldb_private::Mutex::Locker& locker, const char *failure_message = NULL);
63 
64     bool
65     CheckForPacket (const uint8_t *src,
66                     size_t src_len,
67                     StringExtractorGDBRemote &packet);
68     bool
IsRunning()69     IsRunning() const
70     {
71         return m_public_is_running.GetValue();
72     }
73 
74     bool
GetSendAcks()75     GetSendAcks ()
76     {
77         return m_send_acks;
78     }
79 
80     //------------------------------------------------------------------
81     // Client and server must implement these pure virtual functions
82     //------------------------------------------------------------------
83     virtual bool
84     GetThreadSuffixSupported () = 0;
85 
86     //------------------------------------------------------------------
87     // Set the global packet timeout.
88     //
89     // For clients, this is the timeout that gets used when sending
90     // packets and waiting for responses. For servers, this might not
91     // get used, and if it doesn't this should be moved to the
92     // GDBRemoteCommunicationClient.
93     //------------------------------------------------------------------
94     uint32_t
SetPacketTimeout(uint32_t packet_timeout)95     SetPacketTimeout (uint32_t packet_timeout)
96     {
97         const uint32_t old_packet_timeout = m_packet_timeout;
98         m_packet_timeout = packet_timeout;
99         return old_packet_timeout;
100     }
101 
102     uint32_t
GetPacketTimeoutInMicroSeconds()103     GetPacketTimeoutInMicroSeconds () const
104     {
105         return m_packet_timeout * lldb_private::TimeValue::MicroSecPerSec;
106     }
107     //------------------------------------------------------------------
108     // Start a debugserver instance on the current host using the
109     // supplied connection URL.
110     //------------------------------------------------------------------
111     lldb_private::Error
112     StartDebugserverProcess (const char *connect_url,
113                              const char *unix_socket_name,
114                              lldb_private::ProcessLaunchInfo &launch_info);
115 
116     void
117     DumpHistory(lldb_private::Stream &strm);
118 
119 protected:
120 
121     class History
122     {
123     public:
124         enum PacketType
125         {
126             ePacketTypeInvalid = 0,
127             ePacketTypeSend,
128             ePacketTypeRecv
129         };
130 
131         struct Entry
132         {
EntryEntry133             Entry() :
134                 packet(),
135                 type (ePacketTypeInvalid),
136                 bytes_transmitted (0),
137                 packet_idx (0),
138                 tid (LLDB_INVALID_THREAD_ID)
139             {
140             }
141 
142             void
ClearEntry143             Clear ()
144             {
145                 packet.clear();
146                 type = ePacketTypeInvalid;
147                 bytes_transmitted = 0;
148                 packet_idx = 0;
149                 tid = LLDB_INVALID_THREAD_ID;
150             }
151             std::string packet;
152             PacketType type;
153             uint32_t bytes_transmitted;
154             uint32_t packet_idx;
155             lldb::tid_t tid;
156         };
157 
158         History (uint32_t size);
159 
160         ~History ();
161 
162         // For single char packets for ack, nack and /x03
163         void
164         AddPacket (char packet_char,
165                    PacketType type,
166                    uint32_t bytes_transmitted);
167         void
168         AddPacket (const std::string &src,
169                    uint32_t src_len,
170                    PacketType type,
171                    uint32_t bytes_transmitted);
172 
173         void
174         Dump (lldb_private::Stream &strm) const;
175 
176         void
177         Dump (lldb_private::Log *log) const;
178 
179         bool
DidDumpToLog()180         DidDumpToLog () const
181         {
182             return m_dumped_to_log;
183         }
184 
185 protected:
186         uint32_t
GetFirstSavedPacketIndex()187         GetFirstSavedPacketIndex () const
188         {
189             if (m_total_packet_count < m_packets.size())
190                 return 0;
191             else
192                 return m_curr_idx + 1;
193         }
194 
195         uint32_t
GetNumPacketsInHistory()196         GetNumPacketsInHistory () const
197         {
198             if (m_total_packet_count < m_packets.size())
199                 return m_total_packet_count;
200             else
201                 return (uint32_t)m_packets.size();
202         }
203 
204         uint32_t
GetNextIndex()205         GetNextIndex()
206         {
207             ++m_total_packet_count;
208             const uint32_t idx = m_curr_idx;
209             m_curr_idx = NormalizeIndex(idx + 1);
210             return idx;
211         }
212 
213         uint32_t
NormalizeIndex(uint32_t i)214         NormalizeIndex (uint32_t i) const
215         {
216             return i % m_packets.size();
217         }
218 
219 
220         std::vector<Entry> m_packets;
221         uint32_t m_curr_idx;
222         uint32_t m_total_packet_count;
223         mutable bool m_dumped_to_log;
224     };
225 
226     size_t
227     SendPacket (const char *payload,
228                 size_t payload_length);
229 
230     size_t
231     SendPacketNoLock (const char *payload,
232                       size_t payload_length);
233 
234     size_t
235     WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &response,
236                                                 uint32_t timeout_usec);
237 
238     bool
239     WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr);
240 
241     //------------------------------------------------------------------
242     // Classes that inherit from GDBRemoteCommunication can see and modify these
243     //------------------------------------------------------------------
244     uint32_t m_packet_timeout;
245 #ifdef LLDB_CONFIGURATION_DEBUG
246     lldb_private::TrackingMutex m_sequence_mutex;
247 #else
248     lldb_private::Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time
249 #endif
250     lldb_private::Predicate<bool> m_public_is_running;
251     lldb_private::Predicate<bool> m_private_is_running;
252     History m_history;
253     bool m_send_acks;
254     bool m_is_platform; // Set to true if this class represents a platform,
255                         // false if this class represents a debug session for
256                         // a single process
257 
258 
259 
260 
261 private:
262     //------------------------------------------------------------------
263     // For GDBRemoteCommunication only
264     //------------------------------------------------------------------
265     DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication);
266 };
267 
268 #endif  // liblldb_GDBRemoteCommunication_h_
269