xref: /llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (revision e13c2731ba83ce3f820026878240f72d3b7df0d5)
1 //===-- GDBRemoteCommunicationServer.cpp ------------------------*- 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 #include <errno.h>
11 
12 #include "lldb/Host/Config.h"
13 
14 #include "GDBRemoteCommunicationServer.h"
15 
16 // C Includes
17 // C++ Includes
18 #include <cstring>
19 
20 // Project includes
21 #include "ProcessGDBRemoteLog.h"
22 #include "Utility/StringExtractorGDBRemote.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(const char *comm_name,
28                                                            const char *listener_name) :
29     GDBRemoteCommunication (comm_name, listener_name),
30     m_exit_now (false)
31 {
32 }
33 
34 GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
35 {
36 }
37 
38 void GDBRemoteCommunicationServer::RegisterPacketHandler(
39         StringExtractorGDBRemote::ServerPacketType packet_type,
40         PacketHandler handler)
41 {
42     m_packet_handlers[packet_type] = std::move(handler);
43 }
44 
45 GDBRemoteCommunication::PacketResult
46 GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
47                                                         Error &error,
48                                                         bool &interrupt,
49                                                         bool &quit)
50 {
51     StringExtractorGDBRemote packet;
52 
53     PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
54     if (packet_result == PacketResult::Success)
55     {
56         const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
57         switch (packet_type)
58         {
59         case StringExtractorGDBRemote::eServerPacketType_nack:
60         case StringExtractorGDBRemote::eServerPacketType_ack:
61             break;
62 
63         case StringExtractorGDBRemote::eServerPacketType_invalid:
64             error.SetErrorString("invalid packet");
65             quit = true;
66             break;
67 
68         case StringExtractorGDBRemote::eServerPacketType_unimplemented:
69             packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
70             break;
71 
72         default:
73             auto handler_it = m_packet_handlers.find(packet_type);
74             if (handler_it == m_packet_handlers.end())
75                 packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
76             else
77                 packet_result = handler_it->second (packet, error, interrupt, quit);
78             break;
79         }
80     }
81     else
82     {
83         if (!IsConnected())
84         {
85             error.SetErrorString("lost connection");
86             quit = true;
87         }
88         else
89         {
90             error.SetErrorString("timeout");
91         }
92     }
93 
94     // Check if anything occurred that would force us to want to exit.
95     if (m_exit_now)
96         quit = true;
97 
98     return packet_result;
99 }
100 
101 GDBRemoteCommunication::PacketResult
102 GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
103 {
104     // TODO: Log the packet we aren't handling...
105     return SendPacketNoLock ("", 0);
106 }
107 
108 
109 GDBRemoteCommunication::PacketResult
110 GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
111 {
112     char packet[16];
113     int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
114     assert (packet_len < (int)sizeof(packet));
115     return SendPacketNoLock (packet, packet_len);
116 }
117 
118 GDBRemoteCommunication::PacketResult
119 GDBRemoteCommunicationServer::SendIllFormedResponse (const StringExtractorGDBRemote &failed_packet, const char *message)
120 {
121     Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
122     if (log)
123         log->Printf ("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", __FUNCTION__, failed_packet.GetStringRef ().c_str (), message ? message : "");
124     return SendErrorResponse (0x03);
125 }
126 
127 GDBRemoteCommunication::PacketResult
128 GDBRemoteCommunicationServer::SendOKResponse ()
129 {
130     return SendPacketNoLock ("OK", 2);
131 }
132 
133 bool
134 GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
135 {
136     return GetAck() == PacketResult::Success;
137 }
138