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