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