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