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